aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/kvm/svm.c33
1 files changed, 31 insertions, 2 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index a1a83b955ed7..07655345f50b 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -88,6 +88,14 @@ struct nested_state {
88 /* A VMEXIT is required but not yet emulated */ 88 /* A VMEXIT is required but not yet emulated */
89 bool exit_required; 89 bool exit_required;
90 90
91 /*
92 * If we vmexit during an instruction emulation we need this to restore
93 * the l1 guest rip after the emulation
94 */
95 unsigned long vmexit_rip;
96 unsigned long vmexit_rsp;
97 unsigned long vmexit_rax;
98
91 /* cache for intercepts of the guest */ 99 /* cache for intercepts of the guest */
92 u16 intercept_cr_read; 100 u16 intercept_cr_read;
93 u16 intercept_cr_write; 101 u16 intercept_cr_write;
@@ -1213,8 +1221,12 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
1213 if (old == new) { 1221 if (old == new) {
1214 /* cr0 write with ts and mp unchanged */ 1222 /* cr0 write with ts and mp unchanged */
1215 svm->vmcb->control.exit_code = SVM_EXIT_CR0_SEL_WRITE; 1223 svm->vmcb->control.exit_code = SVM_EXIT_CR0_SEL_WRITE;
1216 if (nested_svm_exit_handled(svm) == NESTED_EXIT_DONE) 1224 if (nested_svm_exit_handled(svm) == NESTED_EXIT_DONE) {
1225 svm->nested.vmexit_rip = kvm_rip_read(vcpu);
1226 svm->nested.vmexit_rsp = kvm_register_read(vcpu, VCPU_REGS_RSP);
1227 svm->nested.vmexit_rax = kvm_register_read(vcpu, VCPU_REGS_RAX);
1217 return; 1228 return;
1229 }
1218 } 1230 }
1219 } 1231 }
1220 1232
@@ -2430,6 +2442,23 @@ static int emulate_on_interception(struct vcpu_svm *svm)
2430 return emulate_instruction(&svm->vcpu, 0, 0, 0) == EMULATE_DONE; 2442 return emulate_instruction(&svm->vcpu, 0, 0, 0) == EMULATE_DONE;
2431} 2443}
2432 2444
2445static int cr0_write_interception(struct vcpu_svm *svm)
2446{
2447 struct kvm_vcpu *vcpu = &svm->vcpu;
2448 int r;
2449
2450 r = emulate_instruction(&svm->vcpu, 0, 0, 0);
2451
2452 if (svm->nested.vmexit_rip) {
2453 kvm_register_write(vcpu, VCPU_REGS_RIP, svm->nested.vmexit_rip);
2454 kvm_register_write(vcpu, VCPU_REGS_RSP, svm->nested.vmexit_rsp);
2455 kvm_register_write(vcpu, VCPU_REGS_RAX, svm->nested.vmexit_rax);
2456 svm->nested.vmexit_rip = 0;
2457 }
2458
2459 return r == EMULATE_DONE;
2460}
2461
2433static int cr8_write_interception(struct vcpu_svm *svm) 2462static int cr8_write_interception(struct vcpu_svm *svm)
2434{ 2463{
2435 struct kvm_run *kvm_run = svm->vcpu.run; 2464 struct kvm_run *kvm_run = svm->vcpu.run;
@@ -2692,7 +2721,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm) = {
2692 [SVM_EXIT_READ_CR4] = emulate_on_interception, 2721 [SVM_EXIT_READ_CR4] = emulate_on_interception,
2693 [SVM_EXIT_READ_CR8] = emulate_on_interception, 2722 [SVM_EXIT_READ_CR8] = emulate_on_interception,
2694 [SVM_EXIT_CR0_SEL_WRITE] = emulate_on_interception, 2723 [SVM_EXIT_CR0_SEL_WRITE] = emulate_on_interception,
2695 [SVM_EXIT_WRITE_CR0] = emulate_on_interception, 2724 [SVM_EXIT_WRITE_CR0] = cr0_write_interception,
2696 [SVM_EXIT_WRITE_CR3] = emulate_on_interception, 2725 [SVM_EXIT_WRITE_CR3] = emulate_on_interception,
2697 [SVM_EXIT_WRITE_CR4] = emulate_on_interception, 2726 [SVM_EXIT_WRITE_CR4] = emulate_on_interception,
2698 [SVM_EXIT_WRITE_CR8] = cr8_write_interception, 2727 [SVM_EXIT_WRITE_CR8] = cr8_write_interception,