aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/svm.c
diff options
context:
space:
mode:
authorBoris Ostrovsky <boris.ostrovsky@amd.com>2012-01-09 14:00:35 -0500
committerAvi Kivity <avi@redhat.com>2012-03-05 07:52:21 -0500
commit2b036c6b861dc5da295c6fe19a3edcff7093fdeb (patch)
tree6c329a86190f3d071946864643fee0d851387985 /arch/x86/kvm/svm.c
parent4a58ae614a28b1ae3bea1c74a307cdfb7c77dab8 (diff)
KVM: SVM: Add support for AMD's OSVW feature in guests
In some cases guests should not provide workarounds for errata even when the physical processor is affected. For example, because of erratum 400 on family 10h processors a Linux guest will read an MSR (resulting in VMEXIT) before going to idle in order to avoid getting stuck in a non-C0 state. This is not necessary: HLT and IO instructions are intercepted and therefore there is no reason for erratum 400 workaround in the guest. This patch allows us to present a guest with certain errata as fixed, regardless of the state of actual hardware. Signed-off-by: Boris Ostrovsky <boris.ostrovsky@amd.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
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: