aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/vmx.c
diff options
context:
space:
mode:
authorMarcelo Tosatti <mtosatti@redhat.com>2007-12-20 19:18:22 -0500
committerAvi Kivity <avi@qumranet.com>2008-01-30 11:01:20 -0500
commit10589a4699bb978c781ce73bbae8ca942c5250c9 (patch)
tree5585ed87fff0a2ba259fcc6f998022481da75f68 /arch/x86/kvm/vmx.c
parent774ead3ad9bcbc05ef6aaebb9bdf8b4c3126923b (diff)
KVM: MMU: Concurrent guest walkers
Do not hold kvm->lock mutex across the entire pagefault code, only acquire it in places where it is necessary, such as mmu hash list, active list, rmap and parent pte handling. Allow concurrent guest walkers by switching walk_addr() to use mmap_sem in read-mode. And get rid of the lockless __gfn_to_page. [avi: move kvm_mmu_pte_write() locking inside the function] [avi: add locking for real mode] [avi: fix cmpxchg locking] Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r--arch/x86/kvm/vmx.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index d1167fc303d6..c39493feba46 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -1432,27 +1432,34 @@ static int init_rmode_tss(struct kvm *kvm)
1432{ 1432{
1433 gfn_t fn = rmode_tss_base(kvm) >> PAGE_SHIFT; 1433 gfn_t fn = rmode_tss_base(kvm) >> PAGE_SHIFT;
1434 u16 data = 0; 1434 u16 data = 0;
1435 int ret = 0;
1435 int r; 1436 int r;
1436 1437
1438 down_read(&current->mm->mmap_sem);
1437 r = kvm_clear_guest_page(kvm, fn, 0, PAGE_SIZE); 1439 r = kvm_clear_guest_page(kvm, fn, 0, PAGE_SIZE);
1438 if (r < 0) 1440 if (r < 0)
1439 return 0; 1441 goto out;
1440 data = TSS_BASE_SIZE + TSS_REDIRECTION_SIZE; 1442 data = TSS_BASE_SIZE + TSS_REDIRECTION_SIZE;
1441 r = kvm_write_guest_page(kvm, fn++, &data, 0x66, sizeof(u16)); 1443 r = kvm_write_guest_page(kvm, fn++, &data, 0x66, sizeof(u16));
1442 if (r < 0) 1444 if (r < 0)
1443 return 0; 1445 goto out;
1444 r = kvm_clear_guest_page(kvm, fn++, 0, PAGE_SIZE); 1446 r = kvm_clear_guest_page(kvm, fn++, 0, PAGE_SIZE);
1445 if (r < 0) 1447 if (r < 0)
1446 return 0; 1448 goto out;
1447 r = kvm_clear_guest_page(kvm, fn, 0, PAGE_SIZE); 1449 r = kvm_clear_guest_page(kvm, fn, 0, PAGE_SIZE);
1448 if (r < 0) 1450 if (r < 0)
1449 return 0; 1451 goto out;
1450 data = ~0; 1452 data = ~0;
1451 r = kvm_write_guest_page(kvm, fn, &data, RMODE_TSS_SIZE - 2 * PAGE_SIZE - 1, 1453 r = kvm_write_guest_page(kvm, fn, &data,
1452 sizeof(u8)); 1454 RMODE_TSS_SIZE - 2 * PAGE_SIZE - 1,
1455 sizeof(u8));
1453 if (r < 0) 1456 if (r < 0)
1454 return 0; 1457 goto out;
1455 return 1; 1458
1459 ret = 1;
1460out:
1461 up_read(&current->mm->mmap_sem);
1462 return ret;
1456} 1463}
1457 1464
1458static void seg_setup(int seg) 1465static void seg_setup(int seg)
@@ -1471,6 +1478,7 @@ static int alloc_apic_access_page(struct kvm *kvm)
1471 int r = 0; 1478 int r = 0;
1472 1479
1473 mutex_lock(&kvm->lock); 1480 mutex_lock(&kvm->lock);
1481 down_write(&current->mm->mmap_sem);
1474 if (kvm->arch.apic_access_page) 1482 if (kvm->arch.apic_access_page)
1475 goto out; 1483 goto out;
1476 kvm_userspace_mem.slot = APIC_ACCESS_PAGE_PRIVATE_MEMSLOT; 1484 kvm_userspace_mem.slot = APIC_ACCESS_PAGE_PRIVATE_MEMSLOT;
@@ -1482,6 +1490,7 @@ static int alloc_apic_access_page(struct kvm *kvm)
1482 goto out; 1490 goto out;
1483 kvm->arch.apic_access_page = gfn_to_page(kvm, 0xfee00); 1491 kvm->arch.apic_access_page = gfn_to_page(kvm, 0xfee00);
1484out: 1492out:
1493 up_write(&current->mm->mmap_sem);
1485 mutex_unlock(&kvm->lock); 1494 mutex_unlock(&kvm->lock);
1486 return r; 1495 return r;
1487} 1496}