diff options
author | Andre Przywara <andre.przywara@amd.com> | 2009-01-11 16:39:44 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-03-24 05:03:11 -0400 |
commit | 1fbdc7a58512a6283e10fd27108197679db95ffa (patch) | |
tree | 3bf28be900d822b54b76afce97d9ed4d6a4ede5f | |
parent | 4925663a079c77d95d8685228ad6675fc5639c8e (diff) |
KVM: SVM: set accessed bit for VMCB segment selectors
In the segment descriptor _cache_ the accessed bit is always set
(although it can be cleared in the descriptor itself). Since Intel
checks for this condition on a VMENTRY, set this bit in the AMD path
to enable cross vendor migration.
Cc: stable@kernel.org
Signed-off-by: Andre Przywara <andre.przywara@amd.com>
Acked-By: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r-- | arch/x86/kvm/svm.c | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 22e88a4a51c7..1821c2078199 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -796,20 +796,37 @@ static void svm_get_segment(struct kvm_vcpu *vcpu, | |||
796 | var->db = (s->attrib >> SVM_SELECTOR_DB_SHIFT) & 1; | 796 | var->db = (s->attrib >> SVM_SELECTOR_DB_SHIFT) & 1; |
797 | var->g = (s->attrib >> SVM_SELECTOR_G_SHIFT) & 1; | 797 | var->g = (s->attrib >> SVM_SELECTOR_G_SHIFT) & 1; |
798 | 798 | ||
799 | /* | 799 | switch (seg) { |
800 | * SVM always stores 0 for the 'G' bit in the CS selector in | 800 | case VCPU_SREG_CS: |
801 | * the VMCB on a VMEXIT. This hurts cross-vendor migration: | 801 | /* |
802 | * Intel's VMENTRY has a check on the 'G' bit. | 802 | * SVM always stores 0 for the 'G' bit in the CS selector in |
803 | */ | 803 | * the VMCB on a VMEXIT. This hurts cross-vendor migration: |
804 | if (seg == VCPU_SREG_CS) | 804 | * Intel's VMENTRY has a check on the 'G' bit. |
805 | */ | ||
805 | var->g = s->limit > 0xfffff; | 806 | var->g = s->limit > 0xfffff; |
806 | 807 | break; | |
807 | /* | 808 | case VCPU_SREG_TR: |
808 | * Work around a bug where the busy flag in the tr selector | 809 | /* |
809 | * isn't exposed | 810 | * Work around a bug where the busy flag in the tr selector |
810 | */ | 811 | * isn't exposed |
811 | if (seg == VCPU_SREG_TR) | 812 | */ |
812 | var->type |= 0x2; | 813 | var->type |= 0x2; |
814 | break; | ||
815 | case VCPU_SREG_DS: | ||
816 | case VCPU_SREG_ES: | ||
817 | case VCPU_SREG_FS: | ||
818 | case VCPU_SREG_GS: | ||
819 | /* | ||
820 | * The accessed bit must always be set in the segment | ||
821 | * descriptor cache, although it can be cleared in the | ||
822 | * descriptor, the cached bit always remains at 1. Since | ||
823 | * Intel has a check on this, set it here to support | ||
824 | * cross-vendor migration. | ||
825 | */ | ||
826 | if (!var->unusable) | ||
827 | var->type |= 0x1; | ||
828 | break; | ||
829 | } | ||
813 | 830 | ||
814 | var->unusable = !var->present; | 831 | var->unusable = !var->present; |
815 | } | 832 | } |