diff options
author | Sheng Yang <sheng.yang@intel.com> | 2007-10-28 21:40:42 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-01-30 10:52:58 -0500 |
commit | f78e0e2ee498e8f847500b565792c7d7634dcf54 (patch) | |
tree | dfd8f35883b40939a1ec013e27e6303af06d3e77 /drivers/kvm/kvm_main.c | |
parent | a03490ed29d2771c675d4d9c0ffe22e19a1757f3 (diff) |
KVM: VMX: Enable memory mapped TPR shadow (FlexPriority)
This patch based on CR8/TPR patch, and enable the TPR shadow (FlexPriority)
for 32bit Windows. Since TPR is accessed very frequently by 32bit
Windows, especially SMP guest, with FlexPriority enabled, we saw significant
performance gain.
Signed-off-by: Sheng Yang <sheng.yang@intel.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/kvm_main.c')
-rw-r--r-- | drivers/kvm/kvm_main.c | 56 |
1 files changed, 39 insertions, 17 deletions
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index 8f7125710d02..ac5ed00e9065 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c | |||
@@ -362,10 +362,12 @@ EXPORT_SYMBOL_GPL(fx_init); | |||
362 | * space. | 362 | * space. |
363 | * | 363 | * |
364 | * Discontiguous memory is allowed, mostly for framebuffers. | 364 | * Discontiguous memory is allowed, mostly for framebuffers. |
365 | * | ||
366 | * Must be called holding kvm->lock. | ||
365 | */ | 367 | */ |
366 | int kvm_set_memory_region(struct kvm *kvm, | 368 | int __kvm_set_memory_region(struct kvm *kvm, |
367 | struct kvm_userspace_memory_region *mem, | 369 | struct kvm_userspace_memory_region *mem, |
368 | int user_alloc) | 370 | int user_alloc) |
369 | { | 371 | { |
370 | int r; | 372 | int r; |
371 | gfn_t base_gfn; | 373 | gfn_t base_gfn; |
@@ -392,8 +394,6 @@ int kvm_set_memory_region(struct kvm *kvm, | |||
392 | if (!npages) | 394 | if (!npages) |
393 | mem->flags &= ~KVM_MEM_LOG_DIRTY_PAGES; | 395 | mem->flags &= ~KVM_MEM_LOG_DIRTY_PAGES; |
394 | 396 | ||
395 | mutex_lock(&kvm->lock); | ||
396 | |||
397 | new = old = *memslot; | 397 | new = old = *memslot; |
398 | 398 | ||
399 | new.base_gfn = base_gfn; | 399 | new.base_gfn = base_gfn; |
@@ -403,7 +403,7 @@ int kvm_set_memory_region(struct kvm *kvm, | |||
403 | /* Disallow changing a memory slot's size. */ | 403 | /* Disallow changing a memory slot's size. */ |
404 | r = -EINVAL; | 404 | r = -EINVAL; |
405 | if (npages && old.npages && npages != old.npages) | 405 | if (npages && old.npages && npages != old.npages) |
406 | goto out_unlock; | 406 | goto out_free; |
407 | 407 | ||
408 | /* Check for overlaps */ | 408 | /* Check for overlaps */ |
409 | r = -EEXIST; | 409 | r = -EEXIST; |
@@ -414,7 +414,7 @@ int kvm_set_memory_region(struct kvm *kvm, | |||
414 | continue; | 414 | continue; |
415 | if (!((base_gfn + npages <= s->base_gfn) || | 415 | if (!((base_gfn + npages <= s->base_gfn) || |
416 | (base_gfn >= s->base_gfn + s->npages))) | 416 | (base_gfn >= s->base_gfn + s->npages))) |
417 | goto out_unlock; | 417 | goto out_free; |
418 | } | 418 | } |
419 | 419 | ||
420 | /* Free page dirty bitmap if unneeded */ | 420 | /* Free page dirty bitmap if unneeded */ |
@@ -428,7 +428,7 @@ int kvm_set_memory_region(struct kvm *kvm, | |||
428 | new.rmap = vmalloc(npages * sizeof(struct page *)); | 428 | new.rmap = vmalloc(npages * sizeof(struct page *)); |
429 | 429 | ||
430 | if (!new.rmap) | 430 | if (!new.rmap) |
431 | goto out_unlock; | 431 | goto out_free; |
432 | 432 | ||
433 | memset(new.rmap, 0, npages * sizeof(*new.rmap)); | 433 | memset(new.rmap, 0, npages * sizeof(*new.rmap)); |
434 | 434 | ||
@@ -445,7 +445,7 @@ int kvm_set_memory_region(struct kvm *kvm, | |||
445 | up_write(¤t->mm->mmap_sem); | 445 | up_write(¤t->mm->mmap_sem); |
446 | 446 | ||
447 | if (IS_ERR((void *)new.userspace_addr)) | 447 | if (IS_ERR((void *)new.userspace_addr)) |
448 | goto out_unlock; | 448 | goto out_free; |
449 | } | 449 | } |
450 | } else { | 450 | } else { |
451 | if (!old.user_alloc && old.rmap) { | 451 | if (!old.user_alloc && old.rmap) { |
@@ -468,7 +468,7 @@ int kvm_set_memory_region(struct kvm *kvm, | |||
468 | 468 | ||
469 | new.dirty_bitmap = vmalloc(dirty_bytes); | 469 | new.dirty_bitmap = vmalloc(dirty_bytes); |
470 | if (!new.dirty_bitmap) | 470 | if (!new.dirty_bitmap) |
471 | goto out_unlock; | 471 | goto out_free; |
472 | memset(new.dirty_bitmap, 0, dirty_bytes); | 472 | memset(new.dirty_bitmap, 0, dirty_bytes); |
473 | } | 473 | } |
474 | 474 | ||
@@ -498,18 +498,28 @@ int kvm_set_memory_region(struct kvm *kvm, | |||
498 | kvm_mmu_slot_remove_write_access(kvm, mem->slot); | 498 | kvm_mmu_slot_remove_write_access(kvm, mem->slot); |
499 | kvm_flush_remote_tlbs(kvm); | 499 | kvm_flush_remote_tlbs(kvm); |
500 | 500 | ||
501 | mutex_unlock(&kvm->lock); | ||
502 | |||
503 | kvm_free_physmem_slot(&old, &new); | 501 | kvm_free_physmem_slot(&old, &new); |
504 | return 0; | 502 | return 0; |
505 | 503 | ||
506 | out_unlock: | 504 | out_free: |
507 | mutex_unlock(&kvm->lock); | ||
508 | kvm_free_physmem_slot(&new, &old); | 505 | kvm_free_physmem_slot(&new, &old); |
509 | out: | 506 | out: |
510 | return r; | 507 | return r; |
511 | 508 | ||
512 | } | 509 | } |
510 | EXPORT_SYMBOL_GPL(__kvm_set_memory_region); | ||
511 | |||
512 | int kvm_set_memory_region(struct kvm *kvm, | ||
513 | struct kvm_userspace_memory_region *mem, | ||
514 | int user_alloc) | ||
515 | { | ||
516 | int r; | ||
517 | |||
518 | mutex_lock(&kvm->lock); | ||
519 | r = __kvm_set_memory_region(kvm, mem, user_alloc); | ||
520 | mutex_unlock(&kvm->lock); | ||
521 | return r; | ||
522 | } | ||
513 | EXPORT_SYMBOL_GPL(kvm_set_memory_region); | 523 | EXPORT_SYMBOL_GPL(kvm_set_memory_region); |
514 | 524 | ||
515 | int kvm_vm_ioctl_set_memory_region(struct kvm *kvm, | 525 | int kvm_vm_ioctl_set_memory_region(struct kvm *kvm, |
@@ -888,14 +898,21 @@ static int emulator_read_emulated(unsigned long addr, | |||
888 | memcpy(val, vcpu->mmio_data, bytes); | 898 | memcpy(val, vcpu->mmio_data, bytes); |
889 | vcpu->mmio_read_completed = 0; | 899 | vcpu->mmio_read_completed = 0; |
890 | return X86EMUL_CONTINUE; | 900 | return X86EMUL_CONTINUE; |
891 | } else if (emulator_read_std(addr, val, bytes, vcpu) | 901 | } |
892 | == X86EMUL_CONTINUE) | ||
893 | return X86EMUL_CONTINUE; | ||
894 | 902 | ||
895 | gpa = vcpu->mmu.gva_to_gpa(vcpu, addr); | 903 | gpa = vcpu->mmu.gva_to_gpa(vcpu, addr); |
904 | |||
905 | /* For APIC access vmexit */ | ||
906 | if ((gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE) | ||
907 | goto mmio; | ||
908 | |||
909 | if (emulator_read_std(addr, val, bytes, vcpu) | ||
910 | == X86EMUL_CONTINUE) | ||
911 | return X86EMUL_CONTINUE; | ||
896 | if (gpa == UNMAPPED_GVA) | 912 | if (gpa == UNMAPPED_GVA) |
897 | return X86EMUL_PROPAGATE_FAULT; | 913 | return X86EMUL_PROPAGATE_FAULT; |
898 | 914 | ||
915 | mmio: | ||
899 | /* | 916 | /* |
900 | * Is this MMIO handled locally? | 917 | * Is this MMIO handled locally? |
901 | */ | 918 | */ |
@@ -938,9 +955,14 @@ static int emulator_write_emulated_onepage(unsigned long addr, | |||
938 | return X86EMUL_PROPAGATE_FAULT; | 955 | return X86EMUL_PROPAGATE_FAULT; |
939 | } | 956 | } |
940 | 957 | ||
958 | /* For APIC access vmexit */ | ||
959 | if ((gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE) | ||
960 | goto mmio; | ||
961 | |||
941 | if (emulator_write_phys(vcpu, gpa, val, bytes)) | 962 | if (emulator_write_phys(vcpu, gpa, val, bytes)) |
942 | return X86EMUL_CONTINUE; | 963 | return X86EMUL_CONTINUE; |
943 | 964 | ||
965 | mmio: | ||
944 | /* | 966 | /* |
945 | * Is this MMIO handled locally? | 967 | * Is this MMIO handled locally? |
946 | */ | 968 | */ |