]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
KVM: SVM: Don't use kmap_atomic in nested_svm_map
authorJoerg Roedel <joerg.roedel@amd.com>
Fri, 19 Feb 2010 15:23:00 +0000 (16:23 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 5 Jul 2010 18:16:11 +0000 (11:16 -0700)
Use of kmap_atomic disables preemption but if we run in
shadow-shadow mode the vmrun emulation executes kvm_set_cr3
which might sleep or fault. So use kmap instead for
nested_svm_map.

Cc: stable@kernel.org
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
(cherry picked from commit 7597f129d8b6799da7a264e6d6f7401668d3a36d)

arch/x86/kvm/svm.c

index d42e191b17faa89598c6f75d361d136017e34f56..a6fda1c612c7e24bf58367096941065752c9eae9 100644 (file)
@@ -1398,7 +1398,7 @@ static inline int nested_svm_intr(struct vcpu_svm *svm)
        return 0;
 }
 
-static void *nested_svm_map(struct vcpu_svm *svm, u64 gpa, enum km_type idx)
+static void *nested_svm_map(struct vcpu_svm *svm, u64 gpa, struct page **_page)
 {
        struct page *page;
 
@@ -1406,7 +1406,9 @@ static void *nested_svm_map(struct vcpu_svm *svm, u64 gpa, enum km_type idx)
        if (is_error_page(page))
                goto error;
 
-       return kmap_atomic(page, idx);
+       *_page = page;
+
+       return kmap(page);
 
 error:
        kvm_release_page_clean(page);
@@ -1415,16 +1417,9 @@ error:
        return NULL;
 }
 
-static void nested_svm_unmap(void *addr, enum km_type idx)
+static void nested_svm_unmap(struct page *page)
 {
-       struct page *page;
-
-       if (!addr)
-               return;
-
-       page = kmap_atomic_to_page(addr);
-
-       kunmap_atomic(addr, idx);
+       kunmap(page);
        kvm_release_page_dirty(page);
 }
 
@@ -1432,6 +1427,7 @@ static bool nested_svm_exit_handled_msr(struct vcpu_svm *svm)
 {
        u32 param = svm->vmcb->control.exit_info_1 & 1;
        u32 msr = svm->vcpu.arch.regs[VCPU_REGS_RCX];
+       struct page *page;
        bool ret = false;
        u32 t0, t1;
        u8 *msrpm;
@@ -1439,7 +1435,7 @@ static bool nested_svm_exit_handled_msr(struct vcpu_svm *svm)
        if (!(svm->nested.intercept & (1ULL << INTERCEPT_MSR_PROT)))
                return false;
 
-       msrpm = nested_svm_map(svm, svm->nested.vmcb_msrpm, KM_USER0);
+       msrpm = nested_svm_map(svm, svm->nested.vmcb_msrpm, &page);
 
        if (!msrpm)
                goto out;
@@ -1467,7 +1463,7 @@ static bool nested_svm_exit_handled_msr(struct vcpu_svm *svm)
        ret = msrpm[t1] & ((1 << param) << t0);
 
 out:
-       nested_svm_unmap(msrpm, KM_USER0);
+       nested_svm_unmap(page);
 
        return ret;
 }
@@ -1590,6 +1586,7 @@ static int nested_svm_vmexit(struct vcpu_svm *svm)
        struct vmcb *nested_vmcb;
        struct vmcb *hsave = svm->nested.hsave;
        struct vmcb *vmcb = svm->vmcb;
+       struct page *page;
 
        trace_kvm_nested_vmexit_inject(vmcb->control.exit_code,
                                       vmcb->control.exit_info_1,
@@ -1597,7 +1594,7 @@ static int nested_svm_vmexit(struct vcpu_svm *svm)
                                       vmcb->control.exit_int_info,
                                       vmcb->control.exit_int_info_err);
 
-       nested_vmcb = nested_svm_map(svm, svm->nested.vmcb, KM_USER0);
+       nested_vmcb = nested_svm_map(svm, svm->nested.vmcb, &page);
        if (!nested_vmcb)
                return 1;
 
@@ -1687,7 +1684,7 @@ static int nested_svm_vmexit(struct vcpu_svm *svm)
        /* Exit nested SVM mode */
        svm->nested.vmcb = 0;
 
-       nested_svm_unmap(nested_vmcb, KM_USER0);
+       nested_svm_unmap(page);
 
        kvm_mmu_reset_context(&svm->vcpu);
        kvm_mmu_load(&svm->vcpu);
@@ -1698,9 +1695,10 @@ static int nested_svm_vmexit(struct vcpu_svm *svm)
 static bool nested_svm_vmrun_msrpm(struct vcpu_svm *svm)
 {
        u32 *nested_msrpm;
+       struct page *page;
        int i;
 
-       nested_msrpm = nested_svm_map(svm, svm->nested.vmcb_msrpm, KM_USER0);
+       nested_msrpm = nested_svm_map(svm, svm->nested.vmcb_msrpm, &page);
        if (!nested_msrpm)
                return false;
 
@@ -1709,7 +1707,7 @@ static bool nested_svm_vmrun_msrpm(struct vcpu_svm *svm)
 
        svm->vmcb->control.msrpm_base_pa = __pa(svm->nested.msrpm);
 
-       nested_svm_unmap(nested_msrpm, KM_USER0);
+       nested_svm_unmap(page);
 
        return true;
 }
@@ -1719,8 +1717,9 @@ static bool nested_svm_vmrun(struct vcpu_svm *svm)
        struct vmcb *nested_vmcb;
        struct vmcb *hsave = svm->nested.hsave;
        struct vmcb *vmcb = svm->vmcb;
+       struct page *page;
 
-       nested_vmcb = nested_svm_map(svm, svm->vmcb->save.rax, KM_USER0);
+       nested_vmcb = nested_svm_map(svm, svm->vmcb->save.rax, &page);
        if (!nested_vmcb)
                return false;
 
@@ -1832,7 +1831,7 @@ static bool nested_svm_vmrun(struct vcpu_svm *svm)
        svm->vmcb->control.event_inj = nested_vmcb->control.event_inj;
        svm->vmcb->control.event_inj_err = nested_vmcb->control.event_inj_err;
 
-       nested_svm_unmap(nested_vmcb, KM_USER0);
+       nested_svm_unmap(page);
 
        enable_gif(svm);
 
@@ -1858,6 +1857,7 @@ static void nested_svm_vmloadsave(struct vmcb *from_vmcb, struct vmcb *to_vmcb)
 static int vmload_interception(struct vcpu_svm *svm)
 {
        struct vmcb *nested_vmcb;
+       struct page *page;
 
        if (nested_svm_check_permissions(svm))
                return 1;
@@ -1865,12 +1865,12 @@ static int vmload_interception(struct vcpu_svm *svm)
        svm->next_rip = kvm_rip_read(&svm->vcpu) + 3;
        skip_emulated_instruction(&svm->vcpu);
 
-       nested_vmcb = nested_svm_map(svm, svm->vmcb->save.rax, KM_USER0);
+       nested_vmcb = nested_svm_map(svm, svm->vmcb->save.rax, &page);
        if (!nested_vmcb)
                return 1;
 
        nested_svm_vmloadsave(nested_vmcb, svm->vmcb);
-       nested_svm_unmap(nested_vmcb, KM_USER0);
+       nested_svm_unmap(page);
 
        return 1;
 }
@@ -1878,6 +1878,7 @@ static int vmload_interception(struct vcpu_svm *svm)
 static int vmsave_interception(struct vcpu_svm *svm)
 {
        struct vmcb *nested_vmcb;
+       struct page *page;
 
        if (nested_svm_check_permissions(svm))
                return 1;
@@ -1885,12 +1886,12 @@ static int vmsave_interception(struct vcpu_svm *svm)
        svm->next_rip = kvm_rip_read(&svm->vcpu) + 3;
        skip_emulated_instruction(&svm->vcpu);
 
-       nested_vmcb = nested_svm_map(svm, svm->vmcb->save.rax, KM_USER0);
+       nested_vmcb = nested_svm_map(svm, svm->vmcb->save.rax, &page);
        if (!nested_vmcb)
                return 1;
 
        nested_svm_vmloadsave(svm->vmcb, nested_vmcb);
-       nested_svm_unmap(nested_vmcb, KM_USER0);
+       nested_svm_unmap(page);
 
        return 1;
 }