diff options
author | Marcelo Tosatti <mtosatti@redhat.com> | 2007-12-20 19:18:22 -0500 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-01-30 11:01:20 -0500 |
commit | 10589a4699bb978c781ce73bbae8ca942c5250c9 (patch) | |
tree | 5585ed87fff0a2ba259fcc6f998022481da75f68 /arch/x86/kvm/vmx.c | |
parent | 774ead3ad9bcbc05ef6aaebb9bdf8b4c3126923b (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.c | 25 |
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(¤t->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; | ||
1460 | out: | ||
1461 | up_read(¤t->mm->mmap_sem); | ||
1462 | return ret; | ||
1456 | } | 1463 | } |
1457 | 1464 | ||
1458 | static void seg_setup(int seg) | 1465 | static 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(¤t->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); |
1484 | out: | 1492 | out: |
1493 | up_write(¤t->mm->mmap_sem); | ||
1485 | mutex_unlock(&kvm->lock); | 1494 | mutex_unlock(&kvm->lock); |
1486 | return r; | 1495 | return r; |
1487 | } | 1496 | } |