aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kvm/svm.c43
1 files changed, 39 insertions, 4 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 8ace0b0da933..a8ec53fe74f5 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -979,6 +979,7 @@ static void svm_decache_cr4_guest_bits(struct kvm_vcpu *vcpu)
979 979
980static void update_cr0_intercept(struct vcpu_svm *svm) 980static void update_cr0_intercept(struct vcpu_svm *svm)
981{ 981{
982 struct vmcb *vmcb = svm->vmcb;
982 ulong gcr0 = svm->vcpu.arch.cr0; 983 ulong gcr0 = svm->vcpu.arch.cr0;
983 u64 *hcr0 = &svm->vmcb->save.cr0; 984 u64 *hcr0 = &svm->vmcb->save.cr0;
984 985
@@ -990,11 +991,25 @@ static void update_cr0_intercept(struct vcpu_svm *svm)
990 991
991 992
992 if (gcr0 == *hcr0 && svm->vcpu.fpu_active) { 993 if (gcr0 == *hcr0 && svm->vcpu.fpu_active) {
993 svm->vmcb->control.intercept_cr_read &= ~INTERCEPT_CR0_MASK; 994 vmcb->control.intercept_cr_read &= ~INTERCEPT_CR0_MASK;
994 svm->vmcb->control.intercept_cr_write &= ~INTERCEPT_CR0_MASK; 995 vmcb->control.intercept_cr_write &= ~INTERCEPT_CR0_MASK;
996 if (is_nested(svm)) {
997 struct vmcb *hsave = svm->nested.hsave;
998
999 hsave->control.intercept_cr_read &= ~INTERCEPT_CR0_MASK;
1000 hsave->control.intercept_cr_write &= ~INTERCEPT_CR0_MASK;
1001 vmcb->control.intercept_cr_read |= svm->nested.intercept_cr_read;
1002 vmcb->control.intercept_cr_write |= svm->nested.intercept_cr_write;
1003 }
995 } else { 1004 } else {
996 svm->vmcb->control.intercept_cr_read |= INTERCEPT_CR0_MASK; 1005 svm->vmcb->control.intercept_cr_read |= INTERCEPT_CR0_MASK;
997 svm->vmcb->control.intercept_cr_write |= INTERCEPT_CR0_MASK; 1006 svm->vmcb->control.intercept_cr_write |= INTERCEPT_CR0_MASK;
1007 if (is_nested(svm)) {
1008 struct vmcb *hsave = svm->nested.hsave;
1009
1010 hsave->control.intercept_cr_read |= INTERCEPT_CR0_MASK;
1011 hsave->control.intercept_cr_write |= INTERCEPT_CR0_MASK;
1012 }
998 } 1013 }
999} 1014}
1000 1015
@@ -1269,7 +1284,22 @@ static int ud_interception(struct vcpu_svm *svm)
1269static void svm_fpu_activate(struct kvm_vcpu *vcpu) 1284static void svm_fpu_activate(struct kvm_vcpu *vcpu)
1270{ 1285{
1271 struct vcpu_svm *svm = to_svm(vcpu); 1286 struct vcpu_svm *svm = to_svm(vcpu);
1272 svm->vmcb->control.intercept_exceptions &= ~(1 << NM_VECTOR); 1287 u32 excp;
1288
1289 if (is_nested(svm)) {
1290 u32 h_excp, n_excp;
1291
1292 h_excp = svm->nested.hsave->control.intercept_exceptions;
1293 n_excp = svm->nested.intercept_exceptions;
1294 h_excp &= ~(1 << NM_VECTOR);
1295 excp = h_excp | n_excp;
1296 } else {
1297 excp = svm->vmcb->control.intercept_exceptions;
1298 excp &= ~(1 << NM_VECTOR);
1299 }
1300
1301 svm->vmcb->control.intercept_exceptions = excp;
1302
1273 svm->vcpu.fpu_active = 1; 1303 svm->vcpu.fpu_active = 1;
1274 update_cr0_intercept(svm); 1304 update_cr0_intercept(svm);
1275} 1305}
@@ -1513,6 +1543,9 @@ static int nested_svm_exit_special(struct vcpu_svm *svm)
1513 if (!npt_enabled) 1543 if (!npt_enabled)
1514 return NESTED_EXIT_HOST; 1544 return NESTED_EXIT_HOST;
1515 break; 1545 break;
1546 case SVM_EXIT_EXCP_BASE + NM_VECTOR:
1547 nm_interception(svm);
1548 break;
1516 default: 1549 default:
1517 break; 1550 break;
1518 } 1551 }
@@ -2980,8 +3013,10 @@ static void svm_fpu_deactivate(struct kvm_vcpu *vcpu)
2980{ 3013{
2981 struct vcpu_svm *svm = to_svm(vcpu); 3014 struct vcpu_svm *svm = to_svm(vcpu);
2982 3015
2983 update_cr0_intercept(svm);
2984 svm->vmcb->control.intercept_exceptions |= 1 << NM_VECTOR; 3016 svm->vmcb->control.intercept_exceptions |= 1 << NM_VECTOR;
3017 if (is_nested(svm))
3018 svm->nested.hsave->control.intercept_exceptions |= 1 << NM_VECTOR;
3019 update_cr0_intercept(svm);
2985} 3020}
2986 3021
2987static struct kvm_x86_ops svm_x86_ops = { 3022static struct kvm_x86_ops svm_x86_ops = {