aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/svm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/kvm/svm.c')
-rw-r--r--drivers/kvm/svm.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index 714f6a7841cd..c79df79307ed 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -502,6 +502,7 @@ static void init_vmcb(struct vmcb *vmcb)
502 (1ULL << INTERCEPT_IOIO_PROT) | 502 (1ULL << INTERCEPT_IOIO_PROT) |
503 (1ULL << INTERCEPT_MSR_PROT) | 503 (1ULL << INTERCEPT_MSR_PROT) |
504 (1ULL << INTERCEPT_TASK_SWITCH) | 504 (1ULL << INTERCEPT_TASK_SWITCH) |
505 (1ULL << INTERCEPT_SHUTDOWN) |
505 (1ULL << INTERCEPT_VMRUN) | 506 (1ULL << INTERCEPT_VMRUN) |
506 (1ULL << INTERCEPT_VMMCALL) | 507 (1ULL << INTERCEPT_VMMCALL) |
507 (1ULL << INTERCEPT_VMLOAD) | 508 (1ULL << INTERCEPT_VMLOAD) |
@@ -680,14 +681,14 @@ static void svm_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l)
680 681
681static void svm_get_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) 682static void svm_get_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
682{ 683{
683 dt->limit = vcpu->svm->vmcb->save.ldtr.limit; 684 dt->limit = vcpu->svm->vmcb->save.idtr.limit;
684 dt->base = vcpu->svm->vmcb->save.ldtr.base; 685 dt->base = vcpu->svm->vmcb->save.idtr.base;
685} 686}
686 687
687static void svm_set_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) 688static void svm_set_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
688{ 689{
689 vcpu->svm->vmcb->save.ldtr.limit = dt->limit; 690 vcpu->svm->vmcb->save.idtr.limit = dt->limit;
690 vcpu->svm->vmcb->save.ldtr.base = dt->base ; 691 vcpu->svm->vmcb->save.idtr.base = dt->base ;
691} 692}
692 693
693static void svm_get_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) 694static void svm_get_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
@@ -892,6 +893,19 @@ static int pf_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
892 return 0; 893 return 0;
893} 894}
894 895
896static int shutdown_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
897{
898 /*
899 * VMCB is undefined after a SHUTDOWN intercept
900 * so reinitialize it.
901 */
902 memset(vcpu->svm->vmcb, 0, PAGE_SIZE);
903 init_vmcb(vcpu->svm->vmcb);
904
905 kvm_run->exit_reason = KVM_EXIT_SHUTDOWN;
906 return 0;
907}
908
895static int io_get_override(struct kvm_vcpu *vcpu, 909static int io_get_override(struct kvm_vcpu *vcpu,
896 struct vmcb_seg **seg, 910 struct vmcb_seg **seg,
897 int *addr_override) 911 int *addr_override)
@@ -1149,7 +1163,7 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data)
1149 case MSR_K6_STAR: 1163 case MSR_K6_STAR:
1150 vcpu->svm->vmcb->save.star = data; 1164 vcpu->svm->vmcb->save.star = data;
1151 break; 1165 break;
1152#ifdef CONFIG_X86_64_ 1166#ifdef CONFIG_X86_64
1153 case MSR_LSTAR: 1167 case MSR_LSTAR:
1154 vcpu->svm->vmcb->save.lstar = data; 1168 vcpu->svm->vmcb->save.lstar = data;
1155 break; 1169 break;
@@ -1249,6 +1263,7 @@ static int (*svm_exit_handlers[])(struct kvm_vcpu *vcpu,
1249 [SVM_EXIT_IOIO] = io_interception, 1263 [SVM_EXIT_IOIO] = io_interception,
1250 [SVM_EXIT_MSR] = msr_interception, 1264 [SVM_EXIT_MSR] = msr_interception,
1251 [SVM_EXIT_TASK_SWITCH] = task_switch_interception, 1265 [SVM_EXIT_TASK_SWITCH] = task_switch_interception,
1266 [SVM_EXIT_SHUTDOWN] = shutdown_interception,
1252 [SVM_EXIT_VMRUN] = invalid_op_interception, 1267 [SVM_EXIT_VMRUN] = invalid_op_interception,
1253 [SVM_EXIT_VMMCALL] = invalid_op_interception, 1268 [SVM_EXIT_VMMCALL] = invalid_op_interception,
1254 [SVM_EXIT_VMLOAD] = invalid_op_interception, 1269 [SVM_EXIT_VMLOAD] = invalid_op_interception,
@@ -1407,7 +1422,8 @@ static int svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
1407 int r; 1422 int r;
1408 1423
1409again: 1424again:
1410 do_interrupt_requests(vcpu, kvm_run); 1425 if (!vcpu->mmio_read_completed)
1426 do_interrupt_requests(vcpu, kvm_run);
1411 1427
1412 clgi(); 1428 clgi();
1413 1429