aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/x86.c
diff options
context:
space:
mode:
authorIzik Eidus <izike@qumranet.com>2008-02-10 11:04:15 -0500
committerAvi Kivity <avi@qumranet.com>2008-03-04 08:19:40 -0500
commit72dc67a69690288538142df73a7e3ac66fea68dc (patch)
treef40cc5ef0c66686a469977fd438e5b6786f16280 /arch/x86/kvm/x86.c
parentc7ac679c160db864810920df61a6ed14275011aa (diff)
KVM: remove the usage of the mmap_sem for the protection of the memory slots.
This patch replaces the mmap_sem lock for the memory slots with a new kvm private lock, it is needed beacuse untill now there were cases where kvm accesses user memory while holding the mmap semaphore. Signed-off-by: Izik Eidus <izike@qumranet.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r--arch/x86/kvm/x86.c65
1 files changed, 37 insertions, 28 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 338764fa5391..6b01552bd1f1 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -184,7 +184,7 @@ int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3)
184 int ret; 184 int ret;
185 u64 pdpte[ARRAY_SIZE(vcpu->arch.pdptrs)]; 185 u64 pdpte[ARRAY_SIZE(vcpu->arch.pdptrs)];
186 186
187 down_read(&current->mm->mmap_sem); 187 down_read(&vcpu->kvm->slots_lock);
188 ret = kvm_read_guest_page(vcpu->kvm, pdpt_gfn, pdpte, 188 ret = kvm_read_guest_page(vcpu->kvm, pdpt_gfn, pdpte,
189 offset * sizeof(u64), sizeof(pdpte)); 189 offset * sizeof(u64), sizeof(pdpte));
190 if (ret < 0) { 190 if (ret < 0) {
@@ -201,7 +201,7 @@ int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3)
201 201
202 memcpy(vcpu->arch.pdptrs, pdpte, sizeof(vcpu->arch.pdptrs)); 202 memcpy(vcpu->arch.pdptrs, pdpte, sizeof(vcpu->arch.pdptrs));
203out: 203out:
204 up_read(&current->mm->mmap_sem); 204 up_read(&vcpu->kvm->slots_lock);
205 205
206 return ret; 206 return ret;
207} 207}
@@ -215,13 +215,13 @@ static bool pdptrs_changed(struct kvm_vcpu *vcpu)
215 if (is_long_mode(vcpu) || !is_pae(vcpu)) 215 if (is_long_mode(vcpu) || !is_pae(vcpu))
216 return false; 216 return false;
217 217
218 down_read(&current->mm->mmap_sem); 218 down_read(&vcpu->kvm->slots_lock);
219 r = kvm_read_guest(vcpu->kvm, vcpu->arch.cr3 & ~31u, pdpte, sizeof(pdpte)); 219 r = kvm_read_guest(vcpu->kvm, vcpu->arch.cr3 & ~31u, pdpte, sizeof(pdpte));
220 if (r < 0) 220 if (r < 0)
221 goto out; 221 goto out;
222 changed = memcmp(pdpte, vcpu->arch.pdptrs, sizeof(pdpte)) != 0; 222 changed = memcmp(pdpte, vcpu->arch.pdptrs, sizeof(pdpte)) != 0;
223out: 223out:
224 up_read(&current->mm->mmap_sem); 224 up_read(&vcpu->kvm->slots_lock);
225 225
226 return changed; 226 return changed;
227} 227}
@@ -359,7 +359,7 @@ void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
359 */ 359 */
360 } 360 }
361 361
362 down_read(&current->mm->mmap_sem); 362 down_read(&vcpu->kvm->slots_lock);
363 /* 363 /*
364 * Does the new cr3 value map to physical memory? (Note, we 364 * Does the new cr3 value map to physical memory? (Note, we
365 * catch an invalid cr3 even in real-mode, because it would 365 * catch an invalid cr3 even in real-mode, because it would
@@ -375,7 +375,7 @@ void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
375 vcpu->arch.cr3 = cr3; 375 vcpu->arch.cr3 = cr3;
376 vcpu->arch.mmu.new_cr3(vcpu); 376 vcpu->arch.mmu.new_cr3(vcpu);
377 } 377 }
378 up_read(&current->mm->mmap_sem); 378 up_read(&vcpu->kvm->slots_lock);
379} 379}
380EXPORT_SYMBOL_GPL(set_cr3); 380EXPORT_SYMBOL_GPL(set_cr3);
381 381
@@ -1232,12 +1232,12 @@ static int kvm_vm_ioctl_set_nr_mmu_pages(struct kvm *kvm,
1232 if (kvm_nr_mmu_pages < KVM_MIN_ALLOC_MMU_PAGES) 1232 if (kvm_nr_mmu_pages < KVM_MIN_ALLOC_MMU_PAGES)
1233 return -EINVAL; 1233 return -EINVAL;
1234 1234
1235 down_write(&current->mm->mmap_sem); 1235 down_write(&kvm->slots_lock);
1236 1236
1237 kvm_mmu_change_mmu_pages(kvm, kvm_nr_mmu_pages); 1237 kvm_mmu_change_mmu_pages(kvm, kvm_nr_mmu_pages);
1238 kvm->arch.n_requested_mmu_pages = kvm_nr_mmu_pages; 1238 kvm->arch.n_requested_mmu_pages = kvm_nr_mmu_pages;
1239 1239
1240 up_write(&current->mm->mmap_sem); 1240 up_write(&kvm->slots_lock);
1241 return 0; 1241 return 0;
1242} 1242}
1243 1243
@@ -1286,7 +1286,7 @@ static int kvm_vm_ioctl_set_memory_alias(struct kvm *kvm,
1286 < alias->target_phys_addr) 1286 < alias->target_phys_addr)
1287 goto out; 1287 goto out;
1288 1288
1289 down_write(&current->mm->mmap_sem); 1289 down_write(&kvm->slots_lock);
1290 1290
1291 p = &kvm->arch.aliases[alias->slot]; 1291 p = &kvm->arch.aliases[alias->slot];
1292 p->base_gfn = alias->guest_phys_addr >> PAGE_SHIFT; 1292 p->base_gfn = alias->guest_phys_addr >> PAGE_SHIFT;
@@ -1300,7 +1300,7 @@ static int kvm_vm_ioctl_set_memory_alias(struct kvm *kvm,
1300 1300
1301 kvm_mmu_zap_all(kvm); 1301 kvm_mmu_zap_all(kvm);
1302 1302
1303 up_write(&current->mm->mmap_sem); 1303 up_write(&kvm->slots_lock);
1304 1304
1305 return 0; 1305 return 0;
1306 1306
@@ -1376,7 +1376,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
1376 struct kvm_memory_slot *memslot; 1376 struct kvm_memory_slot *memslot;
1377 int is_dirty = 0; 1377 int is_dirty = 0;
1378 1378
1379 down_write(&current->mm->mmap_sem); 1379 down_write(&kvm->slots_lock);
1380 1380
1381 r = kvm_get_dirty_log(kvm, log, &is_dirty); 1381 r = kvm_get_dirty_log(kvm, log, &is_dirty);
1382 if (r) 1382 if (r)
@@ -1392,7 +1392,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
1392 } 1392 }
1393 r = 0; 1393 r = 0;
1394out: 1394out:
1395 up_write(&current->mm->mmap_sem); 1395 up_write(&kvm->slots_lock);
1396 return r; 1396 return r;
1397} 1397}
1398 1398
@@ -1570,7 +1570,7 @@ int emulator_read_std(unsigned long addr,
1570 void *data = val; 1570 void *data = val;
1571 int r = X86EMUL_CONTINUE; 1571 int r = X86EMUL_CONTINUE;
1572 1572
1573 down_read(&current->mm->mmap_sem); 1573 down_read(&vcpu->kvm->slots_lock);
1574 while (bytes) { 1574 while (bytes) {
1575 gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr); 1575 gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
1576 unsigned offset = addr & (PAGE_SIZE-1); 1576 unsigned offset = addr & (PAGE_SIZE-1);
@@ -1592,7 +1592,7 @@ int emulator_read_std(unsigned long addr,
1592 addr += tocopy; 1592 addr += tocopy;
1593 } 1593 }
1594out: 1594out:
1595 up_read(&current->mm->mmap_sem); 1595 up_read(&vcpu->kvm->slots_lock);
1596 return r; 1596 return r;
1597} 1597}
1598EXPORT_SYMBOL_GPL(emulator_read_std); 1598EXPORT_SYMBOL_GPL(emulator_read_std);
@@ -1611,9 +1611,9 @@ static int emulator_read_emulated(unsigned long addr,
1611 return X86EMUL_CONTINUE; 1611 return X86EMUL_CONTINUE;
1612 } 1612 }
1613 1613
1614 down_read(&current->mm->mmap_sem); 1614 down_read(&vcpu->kvm->slots_lock);
1615 gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr); 1615 gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
1616 up_read(&current->mm->mmap_sem); 1616 up_read(&vcpu->kvm->slots_lock);
1617 1617
1618 /* For APIC access vmexit */ 1618 /* For APIC access vmexit */
1619 if ((gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE) 1619 if ((gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE)
@@ -1651,14 +1651,14 @@ static int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
1651{ 1651{
1652 int ret; 1652 int ret;
1653 1653
1654 down_read(&current->mm->mmap_sem); 1654 down_read(&vcpu->kvm->slots_lock);
1655 ret = kvm_write_guest(vcpu->kvm, gpa, val, bytes); 1655 ret = kvm_write_guest(vcpu->kvm, gpa, val, bytes);
1656 if (ret < 0) { 1656 if (ret < 0) {
1657 up_read(&current->mm->mmap_sem); 1657 up_read(&vcpu->kvm->slots_lock);
1658 return 0; 1658 return 0;
1659 } 1659 }
1660 kvm_mmu_pte_write(vcpu, gpa, val, bytes); 1660 kvm_mmu_pte_write(vcpu, gpa, val, bytes);
1661 up_read(&current->mm->mmap_sem); 1661 up_read(&vcpu->kvm->slots_lock);
1662 return 1; 1662 return 1;
1663} 1663}
1664 1664
@@ -1670,9 +1670,9 @@ static int emulator_write_emulated_onepage(unsigned long addr,
1670 struct kvm_io_device *mmio_dev; 1670 struct kvm_io_device *mmio_dev;
1671 gpa_t gpa; 1671 gpa_t gpa;
1672 1672
1673 down_read(&current->mm->mmap_sem); 1673 down_read(&vcpu->kvm->slots_lock);
1674 gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr); 1674 gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
1675 up_read(&current->mm->mmap_sem); 1675 up_read(&vcpu->kvm->slots_lock);
1676 1676
1677 if (gpa == UNMAPPED_GVA) { 1677 if (gpa == UNMAPPED_GVA) {
1678 kvm_inject_page_fault(vcpu, addr, 2); 1678 kvm_inject_page_fault(vcpu, addr, 2);
@@ -1749,7 +1749,7 @@ static int emulator_cmpxchg_emulated(unsigned long addr,
1749 char *kaddr; 1749 char *kaddr;
1750 u64 val; 1750 u64 val;
1751 1751
1752 down_read(&current->mm->mmap_sem); 1752 down_read(&vcpu->kvm->slots_lock);
1753 gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr); 1753 gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
1754 1754
1755 if (gpa == UNMAPPED_GVA || 1755 if (gpa == UNMAPPED_GVA ||
@@ -1760,13 +1760,17 @@ static int emulator_cmpxchg_emulated(unsigned long addr,
1760 goto emul_write; 1760 goto emul_write;
1761 1761
1762 val = *(u64 *)new; 1762 val = *(u64 *)new;
1763
1764 down_read(&current->mm->mmap_sem);
1763 page = gfn_to_page(vcpu->kvm, gpa >> PAGE_SHIFT); 1765 page = gfn_to_page(vcpu->kvm, gpa >> PAGE_SHIFT);
1766 up_read(&current->mm->mmap_sem);
1767
1764 kaddr = kmap_atomic(page, KM_USER0); 1768 kaddr = kmap_atomic(page, KM_USER0);
1765 set_64bit((u64 *)(kaddr + offset_in_page(gpa)), val); 1769 set_64bit((u64 *)(kaddr + offset_in_page(gpa)), val);
1766 kunmap_atomic(kaddr, KM_USER0); 1770 kunmap_atomic(kaddr, KM_USER0);
1767 kvm_release_page_dirty(page); 1771 kvm_release_page_dirty(page);
1768 emul_write: 1772 emul_write:
1769 up_read(&current->mm->mmap_sem); 1773 up_read(&vcpu->kvm->slots_lock);
1770 } 1774 }
1771#endif 1775#endif
1772 1776
@@ -2159,10 +2163,10 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
2159 kvm_x86_ops->skip_emulated_instruction(vcpu); 2163 kvm_x86_ops->skip_emulated_instruction(vcpu);
2160 2164
2161 for (i = 0; i < nr_pages; ++i) { 2165 for (i = 0; i < nr_pages; ++i) {
2162 down_read(&current->mm->mmap_sem); 2166 down_read(&vcpu->kvm->slots_lock);
2163 page = gva_to_page(vcpu, address + i * PAGE_SIZE); 2167 page = gva_to_page(vcpu, address + i * PAGE_SIZE);
2164 vcpu->arch.pio.guest_pages[i] = page; 2168 vcpu->arch.pio.guest_pages[i] = page;
2165 up_read(&current->mm->mmap_sem); 2169 up_read(&vcpu->kvm->slots_lock);
2166 if (!page) { 2170 if (!page) {
2167 kvm_inject_gp(vcpu, 0); 2171 kvm_inject_gp(vcpu, 0);
2168 free_pio_guest_pages(vcpu); 2172 free_pio_guest_pages(vcpu);
@@ -2485,8 +2489,9 @@ static void vapic_enter(struct kvm_vcpu *vcpu)
2485 2489
2486 down_read(&current->mm->mmap_sem); 2490 down_read(&current->mm->mmap_sem);
2487 page = gfn_to_page(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT); 2491 page = gfn_to_page(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT);
2488 vcpu->arch.apic->vapic_page = page;
2489 up_read(&current->mm->mmap_sem); 2492 up_read(&current->mm->mmap_sem);
2493
2494 vcpu->arch.apic->vapic_page = page;
2490} 2495}
2491 2496
2492static void vapic_exit(struct kvm_vcpu *vcpu) 2497static void vapic_exit(struct kvm_vcpu *vcpu)
@@ -2959,9 +2964,9 @@ int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
2959 gpa_t gpa; 2964 gpa_t gpa;
2960 2965
2961 vcpu_load(vcpu); 2966 vcpu_load(vcpu);
2962 down_read(&current->mm->mmap_sem); 2967 down_read(&vcpu->kvm->slots_lock);
2963 gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, vaddr); 2968 gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, vaddr);
2964 up_read(&current->mm->mmap_sem); 2969 up_read(&vcpu->kvm->slots_lock);
2965 tr->physical_address = gpa; 2970 tr->physical_address = gpa;
2966 tr->valid = gpa != UNMAPPED_GVA; 2971 tr->valid = gpa != UNMAPPED_GVA;
2967 tr->writeable = 1; 2972 tr->writeable = 1;
@@ -3234,11 +3239,13 @@ int kvm_arch_set_memory_region(struct kvm *kvm,
3234 */ 3239 */
3235 if (!user_alloc) { 3240 if (!user_alloc) {
3236 if (npages && !old.rmap) { 3241 if (npages && !old.rmap) {
3242 down_write(&current->mm->mmap_sem);
3237 memslot->userspace_addr = do_mmap(NULL, 0, 3243 memslot->userspace_addr = do_mmap(NULL, 0,
3238 npages * PAGE_SIZE, 3244 npages * PAGE_SIZE,
3239 PROT_READ | PROT_WRITE, 3245 PROT_READ | PROT_WRITE,
3240 MAP_SHARED | MAP_ANONYMOUS, 3246 MAP_SHARED | MAP_ANONYMOUS,
3241 0); 3247 0);
3248 up_write(&current->mm->mmap_sem);
3242 3249
3243 if (IS_ERR((void *)memslot->userspace_addr)) 3250 if (IS_ERR((void *)memslot->userspace_addr))
3244 return PTR_ERR((void *)memslot->userspace_addr); 3251 return PTR_ERR((void *)memslot->userspace_addr);
@@ -3246,8 +3253,10 @@ int kvm_arch_set_memory_region(struct kvm *kvm,
3246 if (!old.user_alloc && old.rmap) { 3253 if (!old.user_alloc && old.rmap) {
3247 int ret; 3254 int ret;
3248 3255
3256 down_write(&current->mm->mmap_sem);
3249 ret = do_munmap(current->mm, old.userspace_addr, 3257 ret = do_munmap(current->mm, old.userspace_addr,
3250 old.npages * PAGE_SIZE); 3258 old.npages * PAGE_SIZE);
3259 up_write(&current->mm->mmap_sem);
3251 if (ret < 0) 3260 if (ret < 0)
3252 printk(KERN_WARNING 3261 printk(KERN_WARNING
3253 "kvm_vm_ioctl_set_memory_region: " 3262 "kvm_vm_ioctl_set_memory_region: "