diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-24 15:47:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-24 15:47:25 -0400 |
commit | 1765a1fe5d6f82c0eceb1ad10594cfc83759b6d0 (patch) | |
tree | a701020f0fa3a1932a36d174c5fffd20496303a9 /virt | |
parent | bdaf12b41235b0c59949914de022341e77907461 (diff) | |
parent | 2a31339aa014c0d0b97c57d3ebc997732f8f47fc (diff) |
Merge branch 'kvm-updates/2.6.37' of git://git.kernel.org/pub/scm/virt/kvm/kvm
* 'kvm-updates/2.6.37' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (321 commits)
KVM: Drop CONFIG_DMAR dependency around kvm_iommu_map_pages
KVM: Fix signature of kvm_iommu_map_pages stub
KVM: MCE: Send SRAR SIGBUS directly
KVM: MCE: Add MCG_SER_P into KVM_MCE_CAP_SUPPORTED
KVM: fix typo in copyright notice
KVM: Disable interrupts around get_kernel_ns()
KVM: MMU: Avoid sign extension in mmu_alloc_direct_roots() pae root address
KVM: MMU: move access code parsing to FNAME(walk_addr) function
KVM: MMU: audit: check whether have unsync sps after root sync
KVM: MMU: audit: introduce audit_printk to cleanup audit code
KVM: MMU: audit: unregister audit tracepoints before module unloaded
KVM: MMU: audit: fix vcpu's spte walking
KVM: MMU: set access bit for direct mapping
KVM: MMU: cleanup for error mask set while walk guest page table
KVM: MMU: update 'root_hpa' out of loop in PAE shadow path
KVM: x86 emulator: Eliminate compilation warning in x86_decode_insn()
KVM: x86: Fix constant type in kvm_get_time_scale
KVM: VMX: Add AX to list of registers clobbered by guest switch
KVM guest: Move a printk that's using the clock before it's ready
KVM: x86: TSC catchup mode
...
Diffstat (limited to 'virt')
-rw-r--r-- | virt/kvm/irq_comm.c | 2 | ||||
-rw-r--r-- | virt/kvm/kvm_main.c | 84 |
2 files changed, 67 insertions, 19 deletions
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index 369e38010ad5..8edca9141b78 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c | |||
@@ -17,7 +17,7 @@ | |||
17 | * Authors: | 17 | * Authors: |
18 | * Yaozu (Eddie) Dong <Eddie.dong@intel.com> | 18 | * Yaozu (Eddie) Dong <Eddie.dong@intel.com> |
19 | * | 19 | * |
20 | * Copyright 2010 Red Hat, Inc. and/or its affilates. | 20 | * Copyright 2010 Red Hat, Inc. and/or its affiliates. |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/kvm_host.h> | 23 | #include <linux/kvm_host.h> |
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 60e5e4612b0b..5225052aebc1 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * machines without emulation or binary translation. | 5 | * machines without emulation or binary translation. |
6 | * | 6 | * |
7 | * Copyright (C) 2006 Qumranet, Inc. | 7 | * Copyright (C) 2006 Qumranet, Inc. |
8 | * Copyright 2010 Red Hat, Inc. and/or its affilates. | 8 | * Copyright 2010 Red Hat, Inc. and/or its affiliates. |
9 | * | 9 | * |
10 | * Authors: | 10 | * Authors: |
11 | * Avi Kivity <avi@qumranet.com> | 11 | * Avi Kivity <avi@qumranet.com> |
@@ -705,14 +705,12 @@ skip_lpage: | |||
705 | if (r) | 705 | if (r) |
706 | goto out_free; | 706 | goto out_free; |
707 | 707 | ||
708 | #ifdef CONFIG_DMAR | ||
709 | /* map the pages in iommu page table */ | 708 | /* map the pages in iommu page table */ |
710 | if (npages) { | 709 | if (npages) { |
711 | r = kvm_iommu_map_pages(kvm, &new); | 710 | r = kvm_iommu_map_pages(kvm, &new); |
712 | if (r) | 711 | if (r) |
713 | goto out_free; | 712 | goto out_free; |
714 | } | 713 | } |
715 | #endif | ||
716 | 714 | ||
717 | r = -ENOMEM; | 715 | r = -ENOMEM; |
718 | slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL); | 716 | slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL); |
@@ -927,35 +925,46 @@ int memslot_id(struct kvm *kvm, gfn_t gfn) | |||
927 | return memslot - slots->memslots; | 925 | return memslot - slots->memslots; |
928 | } | 926 | } |
929 | 927 | ||
930 | static unsigned long gfn_to_hva_memslot(struct kvm_memory_slot *slot, gfn_t gfn) | 928 | static unsigned long gfn_to_hva_many(struct kvm *kvm, gfn_t gfn, |
931 | { | 929 | gfn_t *nr_pages) |
932 | return slot->userspace_addr + (gfn - slot->base_gfn) * PAGE_SIZE; | ||
933 | } | ||
934 | |||
935 | unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn) | ||
936 | { | 930 | { |
937 | struct kvm_memory_slot *slot; | 931 | struct kvm_memory_slot *slot; |
938 | 932 | ||
939 | slot = gfn_to_memslot(kvm, gfn); | 933 | slot = gfn_to_memslot(kvm, gfn); |
940 | if (!slot || slot->flags & KVM_MEMSLOT_INVALID) | 934 | if (!slot || slot->flags & KVM_MEMSLOT_INVALID) |
941 | return bad_hva(); | 935 | return bad_hva(); |
936 | |||
937 | if (nr_pages) | ||
938 | *nr_pages = slot->npages - (gfn - slot->base_gfn); | ||
939 | |||
942 | return gfn_to_hva_memslot(slot, gfn); | 940 | return gfn_to_hva_memslot(slot, gfn); |
943 | } | 941 | } |
942 | |||
943 | unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn) | ||
944 | { | ||
945 | return gfn_to_hva_many(kvm, gfn, NULL); | ||
946 | } | ||
944 | EXPORT_SYMBOL_GPL(gfn_to_hva); | 947 | EXPORT_SYMBOL_GPL(gfn_to_hva); |
945 | 948 | ||
946 | static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr) | 949 | static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr, bool atomic) |
947 | { | 950 | { |
948 | struct page *page[1]; | 951 | struct page *page[1]; |
949 | int npages; | 952 | int npages; |
950 | pfn_t pfn; | 953 | pfn_t pfn; |
951 | 954 | ||
952 | might_sleep(); | 955 | if (atomic) |
953 | 956 | npages = __get_user_pages_fast(addr, 1, 1, page); | |
954 | npages = get_user_pages_fast(addr, 1, 1, page); | 957 | else { |
958 | might_sleep(); | ||
959 | npages = get_user_pages_fast(addr, 1, 1, page); | ||
960 | } | ||
955 | 961 | ||
956 | if (unlikely(npages != 1)) { | 962 | if (unlikely(npages != 1)) { |
957 | struct vm_area_struct *vma; | 963 | struct vm_area_struct *vma; |
958 | 964 | ||
965 | if (atomic) | ||
966 | goto return_fault_page; | ||
967 | |||
959 | down_read(¤t->mm->mmap_sem); | 968 | down_read(¤t->mm->mmap_sem); |
960 | if (is_hwpoison_address(addr)) { | 969 | if (is_hwpoison_address(addr)) { |
961 | up_read(¤t->mm->mmap_sem); | 970 | up_read(¤t->mm->mmap_sem); |
@@ -968,6 +977,7 @@ static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr) | |||
968 | if (vma == NULL || addr < vma->vm_start || | 977 | if (vma == NULL || addr < vma->vm_start || |
969 | !(vma->vm_flags & VM_PFNMAP)) { | 978 | !(vma->vm_flags & VM_PFNMAP)) { |
970 | up_read(¤t->mm->mmap_sem); | 979 | up_read(¤t->mm->mmap_sem); |
980 | return_fault_page: | ||
971 | get_page(fault_page); | 981 | get_page(fault_page); |
972 | return page_to_pfn(fault_page); | 982 | return page_to_pfn(fault_page); |
973 | } | 983 | } |
@@ -981,7 +991,13 @@ static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr) | |||
981 | return pfn; | 991 | return pfn; |
982 | } | 992 | } |
983 | 993 | ||
984 | pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn) | 994 | pfn_t hva_to_pfn_atomic(struct kvm *kvm, unsigned long addr) |
995 | { | ||
996 | return hva_to_pfn(kvm, addr, true); | ||
997 | } | ||
998 | EXPORT_SYMBOL_GPL(hva_to_pfn_atomic); | ||
999 | |||
1000 | static pfn_t __gfn_to_pfn(struct kvm *kvm, gfn_t gfn, bool atomic) | ||
985 | { | 1001 | { |
986 | unsigned long addr; | 1002 | unsigned long addr; |
987 | 1003 | ||
@@ -991,7 +1007,18 @@ pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn) | |||
991 | return page_to_pfn(bad_page); | 1007 | return page_to_pfn(bad_page); |
992 | } | 1008 | } |
993 | 1009 | ||
994 | return hva_to_pfn(kvm, addr); | 1010 | return hva_to_pfn(kvm, addr, atomic); |
1011 | } | ||
1012 | |||
1013 | pfn_t gfn_to_pfn_atomic(struct kvm *kvm, gfn_t gfn) | ||
1014 | { | ||
1015 | return __gfn_to_pfn(kvm, gfn, true); | ||
1016 | } | ||
1017 | EXPORT_SYMBOL_GPL(gfn_to_pfn_atomic); | ||
1018 | |||
1019 | pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn) | ||
1020 | { | ||
1021 | return __gfn_to_pfn(kvm, gfn, false); | ||
995 | } | 1022 | } |
996 | EXPORT_SYMBOL_GPL(gfn_to_pfn); | 1023 | EXPORT_SYMBOL_GPL(gfn_to_pfn); |
997 | 1024 | ||
@@ -999,9 +1026,26 @@ pfn_t gfn_to_pfn_memslot(struct kvm *kvm, | |||
999 | struct kvm_memory_slot *slot, gfn_t gfn) | 1026 | struct kvm_memory_slot *slot, gfn_t gfn) |
1000 | { | 1027 | { |
1001 | unsigned long addr = gfn_to_hva_memslot(slot, gfn); | 1028 | unsigned long addr = gfn_to_hva_memslot(slot, gfn); |
1002 | return hva_to_pfn(kvm, addr); | 1029 | return hva_to_pfn(kvm, addr, false); |
1003 | } | 1030 | } |
1004 | 1031 | ||
1032 | int gfn_to_page_many_atomic(struct kvm *kvm, gfn_t gfn, struct page **pages, | ||
1033 | int nr_pages) | ||
1034 | { | ||
1035 | unsigned long addr; | ||
1036 | gfn_t entry; | ||
1037 | |||
1038 | addr = gfn_to_hva_many(kvm, gfn, &entry); | ||
1039 | if (kvm_is_error_hva(addr)) | ||
1040 | return -1; | ||
1041 | |||
1042 | if (entry < nr_pages) | ||
1043 | return 0; | ||
1044 | |||
1045 | return __get_user_pages_fast(addr, nr_pages, 1, pages); | ||
1046 | } | ||
1047 | EXPORT_SYMBOL_GPL(gfn_to_page_many_atomic); | ||
1048 | |||
1005 | struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn) | 1049 | struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn) |
1006 | { | 1050 | { |
1007 | pfn_t pfn; | 1051 | pfn_t pfn; |
@@ -1964,7 +2008,9 @@ static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val, | |||
1964 | case CPU_STARTING: | 2008 | case CPU_STARTING: |
1965 | printk(KERN_INFO "kvm: enabling virtualization on CPU%d\n", | 2009 | printk(KERN_INFO "kvm: enabling virtualization on CPU%d\n", |
1966 | cpu); | 2010 | cpu); |
2011 | spin_lock(&kvm_lock); | ||
1967 | hardware_enable(NULL); | 2012 | hardware_enable(NULL); |
2013 | spin_unlock(&kvm_lock); | ||
1968 | break; | 2014 | break; |
1969 | } | 2015 | } |
1970 | return NOTIFY_OK; | 2016 | return NOTIFY_OK; |
@@ -1977,7 +2023,7 @@ asmlinkage void kvm_handle_fault_on_reboot(void) | |||
1977 | /* spin while reset goes on */ | 2023 | /* spin while reset goes on */ |
1978 | local_irq_enable(); | 2024 | local_irq_enable(); |
1979 | while (true) | 2025 | while (true) |
1980 | ; | 2026 | cpu_relax(); |
1981 | } | 2027 | } |
1982 | /* Fault while not rebooting. We want the trace. */ | 2028 | /* Fault while not rebooting. We want the trace. */ |
1983 | BUG(); | 2029 | BUG(); |
@@ -2171,8 +2217,10 @@ static int kvm_suspend(struct sys_device *dev, pm_message_t state) | |||
2171 | 2217 | ||
2172 | static int kvm_resume(struct sys_device *dev) | 2218 | static int kvm_resume(struct sys_device *dev) |
2173 | { | 2219 | { |
2174 | if (kvm_usage_count) | 2220 | if (kvm_usage_count) { |
2221 | WARN_ON(spin_is_locked(&kvm_lock)); | ||
2175 | hardware_enable(NULL); | 2222 | hardware_enable(NULL); |
2223 | } | ||
2176 | return 0; | 2224 | return 0; |
2177 | } | 2225 | } |
2178 | 2226 | ||