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.c32
1 files changed, 26 insertions, 6 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 27273ed24c41..83c7ab1bdad8 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -571,6 +571,7 @@ static void init_vmcb(struct vcpu_svm *svm)
571 control->intercept = (1ULL << INTERCEPT_INTR) | 571 control->intercept = (1ULL << INTERCEPT_INTR) |
572 (1ULL << INTERCEPT_NMI) | 572 (1ULL << INTERCEPT_NMI) |
573 (1ULL << INTERCEPT_SMI) | 573 (1ULL << INTERCEPT_SMI) |
574 (1ULL << INTERCEPT_SELECTIVE_CR0) |
574 (1ULL << INTERCEPT_CPUID) | 575 (1ULL << INTERCEPT_CPUID) |
575 (1ULL << INTERCEPT_INVD) | 576 (1ULL << INTERCEPT_INVD) |
576 (1ULL << INTERCEPT_HLT) | 577 (1ULL << INTERCEPT_HLT) |
@@ -963,6 +964,27 @@ static void svm_decache_cr4_guest_bits(struct kvm_vcpu *vcpu)
963{ 964{
964} 965}
965 966
967static void update_cr0_intercept(struct vcpu_svm *svm)
968{
969 ulong gcr0 = svm->vcpu.arch.cr0;
970 u64 *hcr0 = &svm->vmcb->save.cr0;
971
972 if (!svm->vcpu.fpu_active)
973 *hcr0 |= SVM_CR0_SELECTIVE_MASK;
974 else
975 *hcr0 = (*hcr0 & ~SVM_CR0_SELECTIVE_MASK)
976 | (gcr0 & SVM_CR0_SELECTIVE_MASK);
977
978
979 if (gcr0 == *hcr0 && svm->vcpu.fpu_active) {
980 svm->vmcb->control.intercept_cr_read &= ~INTERCEPT_CR0_MASK;
981 svm->vmcb->control.intercept_cr_write &= ~INTERCEPT_CR0_MASK;
982 } else {
983 svm->vmcb->control.intercept_cr_read |= INTERCEPT_CR0_MASK;
984 svm->vmcb->control.intercept_cr_write |= INTERCEPT_CR0_MASK;
985 }
986}
987
966static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) 988static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
967{ 989{
968 struct vcpu_svm *svm = to_svm(vcpu); 990 struct vcpu_svm *svm = to_svm(vcpu);
@@ -994,6 +1016,7 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
994 */ 1016 */
995 cr0 &= ~(X86_CR0_CD | X86_CR0_NW); 1017 cr0 &= ~(X86_CR0_CD | X86_CR0_NW);
996 svm->vmcb->save.cr0 = cr0; 1018 svm->vmcb->save.cr0 = cr0;
1019 update_cr0_intercept(svm);
997} 1020}
998 1021
999static void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) 1022static void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
@@ -1239,11 +1262,8 @@ static int ud_interception(struct vcpu_svm *svm)
1239static int nm_interception(struct vcpu_svm *svm) 1262static int nm_interception(struct vcpu_svm *svm)
1240{ 1263{
1241 svm->vmcb->control.intercept_exceptions &= ~(1 << NM_VECTOR); 1264 svm->vmcb->control.intercept_exceptions &= ~(1 << NM_VECTOR);
1242 if (!kvm_read_cr0_bits(&svm->vcpu, X86_CR0_TS))
1243 svm->vmcb->save.cr0 &= ~X86_CR0_TS;
1244 else
1245 svm->vmcb->save.cr0 |= X86_CR0_TS;
1246 svm->vcpu.fpu_active = 1; 1265 svm->vcpu.fpu_active = 1;
1266 update_cr0_intercept(svm);
1247 1267
1248 return 1; 1268 return 1;
1249} 1269}
@@ -2296,7 +2316,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm) = {
2296 [SVM_EXIT_READ_CR3] = emulate_on_interception, 2316 [SVM_EXIT_READ_CR3] = emulate_on_interception,
2297 [SVM_EXIT_READ_CR4] = emulate_on_interception, 2317 [SVM_EXIT_READ_CR4] = emulate_on_interception,
2298 [SVM_EXIT_READ_CR8] = emulate_on_interception, 2318 [SVM_EXIT_READ_CR8] = emulate_on_interception,
2299 /* for now: */ 2319 [SVM_EXIT_CR0_SEL_WRITE] = emulate_on_interception,
2300 [SVM_EXIT_WRITE_CR0] = emulate_on_interception, 2320 [SVM_EXIT_WRITE_CR0] = emulate_on_interception,
2301 [SVM_EXIT_WRITE_CR3] = emulate_on_interception, 2321 [SVM_EXIT_WRITE_CR3] = emulate_on_interception,
2302 [SVM_EXIT_WRITE_CR4] = emulate_on_interception, 2322 [SVM_EXIT_WRITE_CR4] = emulate_on_interception,
@@ -2914,8 +2934,8 @@ static void svm_fpu_deactivate(struct kvm_vcpu *vcpu)
2914 return; 2934 return;
2915 } 2935 }
2916 2936
2937 update_cr0_intercept(svm);
2917 svm->vmcb->control.intercept_exceptions |= 1 << NM_VECTOR; 2938 svm->vmcb->control.intercept_exceptions |= 1 << NM_VECTOR;
2918 svm->vmcb->save.cr0 |= X86_CR0_TS;
2919} 2939}
2920 2940
2921static struct kvm_x86_ops svm_x86_ops = { 2941static struct kvm_x86_ops svm_x86_ops = {