Merge git://oss.sgi.com:8090/xfs/xfs-2.6
[linux-drm-fsl-dcu.git] / drivers / kvm / svm.c
index 714f6a7841cdfbec2bf408153682d00b4b814a12..85f61dd1e9367a4129edd43fecbc6b9b524a0717 100644 (file)
@@ -274,7 +274,7 @@ static void svm_hardware_disable(void *garbage)
                wrmsrl(MSR_VM_HSAVE_PA, 0);
                rdmsrl(MSR_EFER, efer);
                wrmsrl(MSR_EFER, efer & ~MSR_EFER_SVME_MASK);
-               per_cpu(svm_data, raw_smp_processor_id()) = 0;
+               per_cpu(svm_data, raw_smp_processor_id()) = NULL;
                __free_page(svm_data->save_area);
                kfree(svm_data);
        }
@@ -502,6 +502,7 @@ static void init_vmcb(struct vmcb *vmcb)
                                (1ULL << INTERCEPT_IOIO_PROT) |
                                (1ULL << INTERCEPT_MSR_PROT) |
                                (1ULL << INTERCEPT_TASK_SWITCH) |
+                               (1ULL << INTERCEPT_SHUTDOWN) |
                                (1ULL << INTERCEPT_VMRUN) |
                                (1ULL << INTERCEPT_VMMCALL) |
                                (1ULL << INTERCEPT_VMLOAD) |
@@ -641,7 +642,7 @@ static struct vmcb_seg *svm_seg(struct kvm_vcpu *vcpu, int seg)
        case VCPU_SREG_LDTR: return &save->ldtr;
        }
        BUG();
-       return 0;
+       return NULL;
 }
 
 static u64 svm_get_segment_base(struct kvm_vcpu *vcpu, int seg)
@@ -680,14 +681,14 @@ static void svm_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l)
 
 static void svm_get_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
 {
-       dt->limit = vcpu->svm->vmcb->save.ldtr.limit;
-       dt->base = vcpu->svm->vmcb->save.ldtr.base;
+       dt->limit = vcpu->svm->vmcb->save.idtr.limit;
+       dt->base = vcpu->svm->vmcb->save.idtr.base;
 }
 
 static void svm_set_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
 {
-       vcpu->svm->vmcb->save.ldtr.limit = dt->limit;
-       vcpu->svm->vmcb->save.ldtr.base = dt->base ;
+       vcpu->svm->vmcb->save.idtr.limit = dt->limit;
+       vcpu->svm->vmcb->save.idtr.base = dt->base ;
 }
 
 static 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)
        return 0;
 }
 
+static int shutdown_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       /*
+        * VMCB is undefined after a SHUTDOWN intercept
+        * so reinitialize it.
+        */
+       memset(vcpu->svm->vmcb, 0, PAGE_SIZE);
+       init_vmcb(vcpu->svm->vmcb);
+
+       kvm_run->exit_reason = KVM_EXIT_SHUTDOWN;
+       return 0;
+}
+
 static int io_get_override(struct kvm_vcpu *vcpu,
                          struct vmcb_seg **seg,
                          int *addr_override)
@@ -920,7 +934,7 @@ static int io_get_override(struct kvm_vcpu *vcpu,
                return 0;
 
        *addr_override = 0;
-       *seg = 0;
+       *seg = NULL;
        for (i = 0; i < ins_length; i++)
                switch (inst[i]) {
                case 0xf0:
@@ -1073,7 +1087,7 @@ static int cpuid_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
 static int emulate_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
-       if (emulate_instruction(vcpu, 0, 0, 0) != EMULATE_DONE)
+       if (emulate_instruction(vcpu, NULL, 0, 0) != EMULATE_DONE)
                printk(KERN_ERR "%s: failed\n", __FUNCTION__);
        return 1;
 }
@@ -1149,7 +1163,7 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data)
        case MSR_K6_STAR:
                vcpu->svm->vmcb->save.star = data;
                break;
-#ifdef CONFIG_X86_64_
+#ifdef CONFIG_X86_64
        case MSR_LSTAR:
                vcpu->svm->vmcb->save.lstar = data;
                break;
@@ -1249,6 +1263,7 @@ static int (*svm_exit_handlers[])(struct kvm_vcpu *vcpu,
        [SVM_EXIT_IOIO]                         = io_interception,
        [SVM_EXIT_MSR]                          = msr_interception,
        [SVM_EXIT_TASK_SWITCH]                  = task_switch_interception,
+       [SVM_EXIT_SHUTDOWN]                     = shutdown_interception,
        [SVM_EXIT_VMRUN]                        = invalid_op_interception,
        [SVM_EXIT_VMMCALL]                      = invalid_op_interception,
        [SVM_EXIT_VMLOAD]                       = invalid_op_interception,
@@ -1407,7 +1422,8 @@ static int svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        int r;
 
 again:
-       do_interrupt_requests(vcpu, kvm_run);
+       if (!vcpu->mmio_read_completed)
+               do_interrupt_requests(vcpu, kvm_run);
 
        clgi();