aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/svm.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kvm/svm.c')
-rw-r--r--arch/x86/kvm/svm.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 5fa553babe56..fce3ba0f2079 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -110,6 +110,12 @@ struct nested_state {
110#define MSRPM_OFFSETS 16 110#define MSRPM_OFFSETS 16
111static u32 msrpm_offsets[MSRPM_OFFSETS] __read_mostly; 111static u32 msrpm_offsets[MSRPM_OFFSETS] __read_mostly;
112 112
113/*
114 * Set osvw_len to higher value when updated Revision Guides
115 * are published and we know what the new status bits are
116 */
117static uint64_t osvw_len = 4, osvw_status;
118
113struct vcpu_svm { 119struct vcpu_svm {
114 struct kvm_vcpu vcpu; 120 struct kvm_vcpu vcpu;
115 struct vmcb *vmcb; 121 struct vmcb *vmcb;
@@ -556,6 +562,27 @@ static void svm_init_erratum_383(void)
556 erratum_383_found = true; 562 erratum_383_found = true;
557} 563}
558 564
565static void svm_init_osvw(struct kvm_vcpu *vcpu)
566{
567 /*
568 * Guests should see errata 400 and 415 as fixed (assuming that
569 * HLT and IO instructions are intercepted).
570 */
571 vcpu->arch.osvw.length = (osvw_len >= 3) ? (osvw_len) : 3;
572 vcpu->arch.osvw.status = osvw_status & ~(6ULL);
573
574 /*
575 * By increasing VCPU's osvw.length to 3 we are telling the guest that
576 * all osvw.status bits inside that length, including bit 0 (which is
577 * reserved for erratum 298), are valid. However, if host processor's
578 * osvw_len is 0 then osvw_status[0] carries no information. We need to
579 * be conservative here and therefore we tell the guest that erratum 298
580 * is present (because we really don't know).
581 */
582 if (osvw_len == 0 && boot_cpu_data.x86 == 0x10)
583 vcpu->arch.osvw.status |= 1;
584}
585
559static int has_svm(void) 586static int has_svm(void)
560{ 587{
561 const char *msg; 588 const char *msg;
@@ -620,6 +647,36 @@ static int svm_hardware_enable(void *garbage)
620 __get_cpu_var(current_tsc_ratio) = TSC_RATIO_DEFAULT; 647 __get_cpu_var(current_tsc_ratio) = TSC_RATIO_DEFAULT;
621 } 648 }
622 649
650
651 /*
652 * Get OSVW bits.
653 *
654 * Note that it is possible to have a system with mixed processor
655 * revisions and therefore different OSVW bits. If bits are not the same
656 * on different processors then choose the worst case (i.e. if erratum
657 * is present on one processor and not on another then assume that the
658 * erratum is present everywhere).
659 */
660 if (cpu_has(&boot_cpu_data, X86_FEATURE_OSVW)) {
661 uint64_t len, status = 0;
662 int err;
663
664 len = native_read_msr_safe(MSR_AMD64_OSVW_ID_LENGTH, &err);
665 if (!err)
666 status = native_read_msr_safe(MSR_AMD64_OSVW_STATUS,
667 &err);
668
669 if (err)
670 osvw_status = osvw_len = 0;
671 else {
672 if (len < osvw_len)
673 osvw_len = len;
674 osvw_status |= status;
675 osvw_status &= (1ULL << osvw_len) - 1;
676 }
677 } else
678 osvw_status = osvw_len = 0;
679
623 svm_init_erratum_383(); 680 svm_init_erratum_383();
624 681
625 return 0; 682 return 0;
@@ -1186,6 +1243,8 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
1186 if (kvm_vcpu_is_bsp(&svm->vcpu)) 1243 if (kvm_vcpu_is_bsp(&svm->vcpu))
1187 svm->vcpu.arch.apic_base |= MSR_IA32_APICBASE_BSP; 1244 svm->vcpu.arch.apic_base |= MSR_IA32_APICBASE_BSP;
1188 1245
1246 svm_init_osvw(&svm->vcpu);
1247
1189 return &svm->vcpu; 1248 return &svm->vcpu;
1190 1249
1191free_page4: 1250free_page4: