diff options
Diffstat (limited to 'arch/x86/kvm/cpuid.c')
-rw-r--r-- | arch/x86/kvm/cpuid.c | 57 |
1 files changed, 43 insertions, 14 deletions
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 976e3a57f9ea..8a80737ee6e6 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include "mmu.h" | 23 | #include "mmu.h" |
24 | #include "trace.h" | 24 | #include "trace.h" |
25 | 25 | ||
26 | static u32 xstate_required_size(u64 xstate_bv) | 26 | static u32 xstate_required_size(u64 xstate_bv, bool compacted) |
27 | { | 27 | { |
28 | int feature_bit = 0; | 28 | int feature_bit = 0; |
29 | u32 ret = XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET; | 29 | u32 ret = XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET; |
@@ -31,9 +31,10 @@ static u32 xstate_required_size(u64 xstate_bv) | |||
31 | xstate_bv &= XSTATE_EXTEND_MASK; | 31 | xstate_bv &= XSTATE_EXTEND_MASK; |
32 | while (xstate_bv) { | 32 | while (xstate_bv) { |
33 | if (xstate_bv & 0x1) { | 33 | if (xstate_bv & 0x1) { |
34 | u32 eax, ebx, ecx, edx; | 34 | u32 eax, ebx, ecx, edx, offset; |
35 | cpuid_count(0xD, feature_bit, &eax, &ebx, &ecx, &edx); | 35 | cpuid_count(0xD, feature_bit, &eax, &ebx, &ecx, &edx); |
36 | ret = max(ret, eax + ebx); | 36 | offset = compacted ? ret : ebx; |
37 | ret = max(ret, offset + eax); | ||
37 | } | 38 | } |
38 | 39 | ||
39 | xstate_bv >>= 1; | 40 | xstate_bv >>= 1; |
@@ -53,6 +54,8 @@ u64 kvm_supported_xcr0(void) | |||
53 | return xcr0; | 54 | return xcr0; |
54 | } | 55 | } |
55 | 56 | ||
57 | #define F(x) bit(X86_FEATURE_##x) | ||
58 | |||
56 | int kvm_update_cpuid(struct kvm_vcpu *vcpu) | 59 | int kvm_update_cpuid(struct kvm_vcpu *vcpu) |
57 | { | 60 | { |
58 | struct kvm_cpuid_entry2 *best; | 61 | struct kvm_cpuid_entry2 *best; |
@@ -64,13 +67,13 @@ int kvm_update_cpuid(struct kvm_vcpu *vcpu) | |||
64 | 67 | ||
65 | /* Update OSXSAVE bit */ | 68 | /* Update OSXSAVE bit */ |
66 | if (cpu_has_xsave && best->function == 0x1) { | 69 | if (cpu_has_xsave && best->function == 0x1) { |
67 | best->ecx &= ~(bit(X86_FEATURE_OSXSAVE)); | 70 | best->ecx &= ~F(OSXSAVE); |
68 | if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE)) | 71 | if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE)) |
69 | best->ecx |= bit(X86_FEATURE_OSXSAVE); | 72 | best->ecx |= F(OSXSAVE); |
70 | } | 73 | } |
71 | 74 | ||
72 | if (apic) { | 75 | if (apic) { |
73 | if (best->ecx & bit(X86_FEATURE_TSC_DEADLINE_TIMER)) | 76 | if (best->ecx & F(TSC_DEADLINE_TIMER)) |
74 | apic->lapic_timer.timer_mode_mask = 3 << 17; | 77 | apic->lapic_timer.timer_mode_mask = 3 << 17; |
75 | else | 78 | else |
76 | apic->lapic_timer.timer_mode_mask = 1 << 17; | 79 | apic->lapic_timer.timer_mode_mask = 1 << 17; |
@@ -85,9 +88,13 @@ int kvm_update_cpuid(struct kvm_vcpu *vcpu) | |||
85 | (best->eax | ((u64)best->edx << 32)) & | 88 | (best->eax | ((u64)best->edx << 32)) & |
86 | kvm_supported_xcr0(); | 89 | kvm_supported_xcr0(); |
87 | vcpu->arch.guest_xstate_size = best->ebx = | 90 | vcpu->arch.guest_xstate_size = best->ebx = |
88 | xstate_required_size(vcpu->arch.xcr0); | 91 | xstate_required_size(vcpu->arch.xcr0, false); |
89 | } | 92 | } |
90 | 93 | ||
94 | best = kvm_find_cpuid_entry(vcpu, 0xD, 1); | ||
95 | if (best && (best->eax & (F(XSAVES) | F(XSAVEC)))) | ||
96 | best->ebx = xstate_required_size(vcpu->arch.xcr0, true); | ||
97 | |||
91 | /* | 98 | /* |
92 | * The existing code assumes virtual address is 48-bit in the canonical | 99 | * The existing code assumes virtual address is 48-bit in the canonical |
93 | * address checks; exit if it is ever changed. | 100 | * address checks; exit if it is ever changed. |
@@ -122,8 +129,8 @@ static void cpuid_fix_nx_cap(struct kvm_vcpu *vcpu) | |||
122 | break; | 129 | break; |
123 | } | 130 | } |
124 | } | 131 | } |
125 | if (entry && (entry->edx & bit(X86_FEATURE_NX)) && !is_efer_nx()) { | 132 | if (entry && (entry->edx & F(NX)) && !is_efer_nx()) { |
126 | entry->edx &= ~bit(X86_FEATURE_NX); | 133 | entry->edx &= ~F(NX); |
127 | printk(KERN_INFO "kvm: guest NX capability removed\n"); | 134 | printk(KERN_INFO "kvm: guest NX capability removed\n"); |
128 | } | 135 | } |
129 | } | 136 | } |
@@ -227,8 +234,6 @@ static void do_cpuid_1_ent(struct kvm_cpuid_entry2 *entry, u32 function, | |||
227 | entry->flags = 0; | 234 | entry->flags = 0; |
228 | } | 235 | } |
229 | 236 | ||
230 | #define F(x) bit(X86_FEATURE_##x) | ||
231 | |||
232 | static int __do_cpuid_ent_emulated(struct kvm_cpuid_entry2 *entry, | 237 | static int __do_cpuid_ent_emulated(struct kvm_cpuid_entry2 *entry, |
233 | u32 func, u32 index, int *nent, int maxnent) | 238 | u32 func, u32 index, int *nent, int maxnent) |
234 | { | 239 | { |
@@ -267,6 +272,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, | |||
267 | unsigned f_rdtscp = kvm_x86_ops->rdtscp_supported() ? F(RDTSCP) : 0; | 272 | unsigned f_rdtscp = kvm_x86_ops->rdtscp_supported() ? F(RDTSCP) : 0; |
268 | unsigned f_invpcid = kvm_x86_ops->invpcid_supported() ? F(INVPCID) : 0; | 273 | unsigned f_invpcid = kvm_x86_ops->invpcid_supported() ? F(INVPCID) : 0; |
269 | unsigned f_mpx = kvm_x86_ops->mpx_supported() ? F(MPX) : 0; | 274 | unsigned f_mpx = kvm_x86_ops->mpx_supported() ? F(MPX) : 0; |
275 | unsigned f_xsaves = kvm_x86_ops->xsaves_supported() ? F(XSAVES) : 0; | ||
270 | 276 | ||
271 | /* cpuid 1.edx */ | 277 | /* cpuid 1.edx */ |
272 | const u32 kvm_supported_word0_x86_features = | 278 | const u32 kvm_supported_word0_x86_features = |
@@ -317,7 +323,12 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, | |||
317 | const u32 kvm_supported_word9_x86_features = | 323 | const u32 kvm_supported_word9_x86_features = |
318 | F(FSGSBASE) | F(BMI1) | F(HLE) | F(AVX2) | F(SMEP) | | 324 | F(FSGSBASE) | F(BMI1) | F(HLE) | F(AVX2) | F(SMEP) | |
319 | F(BMI2) | F(ERMS) | f_invpcid | F(RTM) | f_mpx | F(RDSEED) | | 325 | F(BMI2) | F(ERMS) | f_invpcid | F(RTM) | f_mpx | F(RDSEED) | |
320 | F(ADX) | F(SMAP); | 326 | F(ADX) | F(SMAP) | F(AVX512F) | F(AVX512PF) | F(AVX512ER) | |
327 | F(AVX512CD); | ||
328 | |||
329 | /* cpuid 0xD.1.eax */ | ||
330 | const u32 kvm_supported_word10_x86_features = | ||
331 | F(XSAVEOPT) | F(XSAVEC) | F(XGETBV1) | f_xsaves; | ||
321 | 332 | ||
322 | /* all calls to cpuid_count() should be made on the same cpu */ | 333 | /* all calls to cpuid_count() should be made on the same cpu */ |
323 | get_cpu(); | 334 | get_cpu(); |
@@ -453,16 +464,34 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, | |||
453 | u64 supported = kvm_supported_xcr0(); | 464 | u64 supported = kvm_supported_xcr0(); |
454 | 465 | ||
455 | entry->eax &= supported; | 466 | entry->eax &= supported; |
467 | entry->ebx = xstate_required_size(supported, false); | ||
468 | entry->ecx = entry->ebx; | ||
456 | entry->edx &= supported >> 32; | 469 | entry->edx &= supported >> 32; |
457 | entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX; | 470 | entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX; |
471 | if (!supported) | ||
472 | break; | ||
473 | |||
458 | for (idx = 1, i = 1; idx < 64; ++idx) { | 474 | for (idx = 1, i = 1; idx < 64; ++idx) { |
459 | u64 mask = ((u64)1 << idx); | 475 | u64 mask = ((u64)1 << idx); |
460 | if (*nent >= maxnent) | 476 | if (*nent >= maxnent) |
461 | goto out; | 477 | goto out; |
462 | 478 | ||
463 | do_cpuid_1_ent(&entry[i], function, idx); | 479 | do_cpuid_1_ent(&entry[i], function, idx); |
464 | if (entry[i].eax == 0 || !(supported & mask)) | 480 | if (idx == 1) { |
465 | continue; | 481 | entry[i].eax &= kvm_supported_word10_x86_features; |
482 | entry[i].ebx = 0; | ||
483 | if (entry[i].eax & (F(XSAVES)|F(XSAVEC))) | ||
484 | entry[i].ebx = | ||
485 | xstate_required_size(supported, | ||
486 | true); | ||
487 | } else { | ||
488 | if (entry[i].eax == 0 || !(supported & mask)) | ||
489 | continue; | ||
490 | if (WARN_ON_ONCE(entry[i].ecx & 1)) | ||
491 | continue; | ||
492 | } | ||
493 | entry[i].ecx = 0; | ||
494 | entry[i].edx = 0; | ||
466 | entry[i].flags |= | 495 | entry[i].flags |= |
467 | KVM_CPUID_FLAG_SIGNIFCANT_INDEX; | 496 | KVM_CPUID_FLAG_SIGNIFCANT_INDEX; |
468 | ++*nent; | 497 | ++*nent; |