Commit 7ff6c035 authored by Sean Christopherson's avatar Sean Christopherson Committed by Paolo Bonzini

KVM: x86: Remove stateful CPUID handling

Remove the code for handling stateful CPUID 0x2 and mark the associated
flags as deprecated.  WARN if host CPUID 0x2.0.AL > 1, i.e. if by some
miracle a host with stateful CPUID 0x2 is encountered.

No known CPU exists that supports hardware accelerated virtualization
_and_ a stateful CPUID 0x2.  Barring an extremely contrived nested
virtualization scenario, stateful CPUID support is dead code.
Suggested-by: default avatarVitaly Kuznetsov <vkuznets@redhat.com>
Suggested-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Signed-off-by: default avatarSean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent c571a144
...@@ -1574,8 +1574,8 @@ This ioctl would set vcpu's xcr to the value userspace specified. ...@@ -1574,8 +1574,8 @@ This ioctl would set vcpu's xcr to the value userspace specified.
}; };
#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX BIT(0) #define KVM_CPUID_FLAG_SIGNIFCANT_INDEX BIT(0)
#define KVM_CPUID_FLAG_STATEFUL_FUNC BIT(1) #define KVM_CPUID_FLAG_STATEFUL_FUNC BIT(1) /* deprecated */
#define KVM_CPUID_FLAG_STATE_READ_NEXT BIT(2) #define KVM_CPUID_FLAG_STATE_READ_NEXT BIT(2) /* deprecated */
struct kvm_cpuid_entry2 { struct kvm_cpuid_entry2 {
__u32 function; __u32 function;
...@@ -1626,13 +1626,6 @@ emulate them efficiently. The fields in each entry are defined as follows: ...@@ -1626,13 +1626,6 @@ emulate them efficiently. The fields in each entry are defined as follows:
KVM_CPUID_FLAG_SIGNIFCANT_INDEX: KVM_CPUID_FLAG_SIGNIFCANT_INDEX:
if the index field is valid if the index field is valid
KVM_CPUID_FLAG_STATEFUL_FUNC:
if cpuid for this function returns different values for successive
invocations; there will be several entries with the same function,
all with this flag set
KVM_CPUID_FLAG_STATE_READ_NEXT:
for KVM_CPUID_FLAG_STATEFUL_FUNC entries, set if this entry is
the first entry to be read by a cpu
eax, ebx, ecx, edx: eax, ebx, ecx, edx:
the values returned by the cpuid instruction for the values returned by the cpuid instruction for
...@@ -3347,8 +3340,8 @@ The member 'flags' is used for passing flags from userspace. ...@@ -3347,8 +3340,8 @@ The member 'flags' is used for passing flags from userspace.
:: ::
#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX BIT(0) #define KVM_CPUID_FLAG_SIGNIFCANT_INDEX BIT(0)
#define KVM_CPUID_FLAG_STATEFUL_FUNC BIT(1) #define KVM_CPUID_FLAG_STATEFUL_FUNC BIT(1) /* deprecated */
#define KVM_CPUID_FLAG_STATE_READ_NEXT BIT(2) #define KVM_CPUID_FLAG_STATE_READ_NEXT BIT(2) /* deprecated */
struct kvm_cpuid_entry2 { struct kvm_cpuid_entry2 {
__u32 function; __u32 function;
...@@ -3394,13 +3387,6 @@ The fields in each entry are defined as follows: ...@@ -3394,13 +3387,6 @@ The fields in each entry are defined as follows:
KVM_CPUID_FLAG_SIGNIFCANT_INDEX: KVM_CPUID_FLAG_SIGNIFCANT_INDEX:
if the index field is valid if the index field is valid
KVM_CPUID_FLAG_STATEFUL_FUNC:
if cpuid for this function returns different values for successive
invocations; there will be several entries with the same function,
all with this flag set
KVM_CPUID_FLAG_STATE_READ_NEXT:
for KVM_CPUID_FLAG_STATEFUL_FUNC entries, set if this entry is
the first entry to be read by a cpu
eax, ebx, ecx, edx: eax, ebx, ecx, edx:
......
...@@ -490,25 +490,16 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) ...@@ -490,25 +490,16 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
* time, with the least-significant byte in EAX enumerating the * time, with the least-significant byte in EAX enumerating the
* number of times software should do CPUID(2, 0). * number of times software should do CPUID(2, 0).
* *
* Modern CPUs (quite likely every CPU KVM has *ever* run on) * Modern CPUs, i.e. every CPU KVM has *ever* run on are less
* are less idiotic. Intel's SDM states that EAX & 0xff "will * idiotic. Intel's SDM states that EAX & 0xff "will always
* always return 01H. Software should ignore this value and not * return 01H. Software should ignore this value and not
* interpret it as an informational descriptor", while AMD's * interpret it as an informational descriptor", while AMD's
* APM states that CPUID(2) is reserved. * APM states that CPUID(2) is reserved.
*
* WARN if a frankenstein CPU that supports virtualization and
* a stateful CPUID.0x2 is encountered.
*/ */
max_idx = entry->eax & 0xff; WARN_ON_ONCE((entry->eax & 0xff) > 1);
if (likely(max_idx <= 1))
break;
entry->flags |= KVM_CPUID_FLAG_STATEFUL_FUNC;
entry->flags |= KVM_CPUID_FLAG_STATE_READ_NEXT;
for (i = 1; i < max_idx; ++i) {
entry = do_host_cpuid(array, function, 0);
if (!entry)
goto out;
entry->flags |= KVM_CPUID_FLAG_STATEFUL_FUNC;
}
break; break;
/* functions 4 and 0x8000001d have additional index. */ /* functions 4 and 0x8000001d have additional index. */
case 4: case 4:
...@@ -892,58 +883,20 @@ int kvm_dev_ioctl_get_cpuid(struct kvm_cpuid2 *cpuid, ...@@ -892,58 +883,20 @@ int kvm_dev_ioctl_get_cpuid(struct kvm_cpuid2 *cpuid,
return r; return r;
} }
static int move_to_next_stateful_cpuid_entry(struct kvm_vcpu *vcpu, int i)
{
struct kvm_cpuid_entry2 *e = &vcpu->arch.cpuid_entries[i];
struct kvm_cpuid_entry2 *ej;
int j = i;
int nent = vcpu->arch.cpuid_nent;
e->flags &= ~KVM_CPUID_FLAG_STATE_READ_NEXT;
/* when no next entry is found, the current entry[i] is reselected */
do {
j = (j + 1) % nent;
ej = &vcpu->arch.cpuid_entries[j];
} while (ej->function != e->function);
ej->flags |= KVM_CPUID_FLAG_STATE_READ_NEXT;
return j;
}
/* find an entry with matching function, matching index (if needed), and that
* should be read next (if it's stateful) */
static int is_matching_cpuid_entry(struct kvm_cpuid_entry2 *e,
u32 function, u32 index)
{
if (e->function != function)
return 0;
if ((e->flags & KVM_CPUID_FLAG_SIGNIFCANT_INDEX) && e->index != index)
return 0;
if (unlikely(e->flags & KVM_CPUID_FLAG_STATEFUL_FUNC) &&
!(e->flags & KVM_CPUID_FLAG_STATE_READ_NEXT))
return 0;
return 1;
}
struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu, struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu,
u32 function, u32 index) u32 function, u32 index)
{ {
struct kvm_cpuid_entry2 *e;
int i; int i;
struct kvm_cpuid_entry2 *best = NULL;
for (i = 0; i < vcpu->arch.cpuid_nent; ++i) { for (i = 0; i < vcpu->arch.cpuid_nent; ++i) {
struct kvm_cpuid_entry2 *e;
e = &vcpu->arch.cpuid_entries[i]; e = &vcpu->arch.cpuid_entries[i];
if (is_matching_cpuid_entry(e, function, index)) {
if (unlikely(e->flags & KVM_CPUID_FLAG_STATEFUL_FUNC)) if (e->function == function && (e->index == index ||
move_to_next_stateful_cpuid_entry(vcpu, i); !(e->flags & KVM_CPUID_FLAG_SIGNIFCANT_INDEX)))
best = e; return e;
break;
}
} }
return best; return NULL;
} }
EXPORT_SYMBOL_GPL(kvm_find_cpuid_entry); EXPORT_SYMBOL_GPL(kvm_find_cpuid_entry);
......
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