diff options
author | Avi Kivity <avi@qumranet.com> | 2008-05-29 07:20:16 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-07-20 05:42:28 -0400 |
commit | eab9f71feb1851b5b700ca12ae614b6a0a441021 (patch) | |
tree | 9e6f7c60206621ab0f876110e2d57f0f7c8759fb /arch/x86 | |
parent | 38d5bc6d50a4368be08b39b02efb9cbbe1dd60d0 (diff) |
KVM: MMU: Optimize prefetch_page()
Instead of reading each pte individually, read 256 bytes worth of ptes and
batch process them.
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kvm/paging_tmpl.h | 28 |
1 files changed, 15 insertions, 13 deletions
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 934c7b619396..4d918220baeb 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h | |||
@@ -460,8 +460,9 @@ static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr) | |||
460 | static void FNAME(prefetch_page)(struct kvm_vcpu *vcpu, | 460 | static void FNAME(prefetch_page)(struct kvm_vcpu *vcpu, |
461 | struct kvm_mmu_page *sp) | 461 | struct kvm_mmu_page *sp) |
462 | { | 462 | { |
463 | int i, offset = 0, r = 0; | 463 | int i, j, offset, r; |
464 | pt_element_t pt; | 464 | pt_element_t pt[256 / sizeof(pt_element_t)]; |
465 | gpa_t pte_gpa; | ||
465 | 466 | ||
466 | if (sp->role.metaphysical | 467 | if (sp->role.metaphysical |
467 | || (PTTYPE == 32 && sp->role.level > PT_PAGE_TABLE_LEVEL)) { | 468 | || (PTTYPE == 32 && sp->role.level > PT_PAGE_TABLE_LEVEL)) { |
@@ -469,19 +470,20 @@ static void FNAME(prefetch_page)(struct kvm_vcpu *vcpu, | |||
469 | return; | 470 | return; |
470 | } | 471 | } |
471 | 472 | ||
472 | if (PTTYPE == 32) | 473 | pte_gpa = gfn_to_gpa(sp->gfn); |
474 | if (PTTYPE == 32) { | ||
473 | offset = sp->role.quadrant << PT64_LEVEL_BITS; | 475 | offset = sp->role.quadrant << PT64_LEVEL_BITS; |
476 | pte_gpa += offset * sizeof(pt_element_t); | ||
477 | } | ||
474 | 478 | ||
475 | for (i = 0; i < PT64_ENT_PER_PAGE; ++i) { | 479 | for (i = 0; i < PT64_ENT_PER_PAGE; i += ARRAY_SIZE(pt)) { |
476 | gpa_t pte_gpa = gfn_to_gpa(sp->gfn); | 480 | r = kvm_read_guest_atomic(vcpu->kvm, pte_gpa, pt, sizeof pt); |
477 | pte_gpa += (i+offset) * sizeof(pt_element_t); | 481 | pte_gpa += ARRAY_SIZE(pt) * sizeof(pt_element_t); |
478 | 482 | for (j = 0; j < ARRAY_SIZE(pt); ++j) | |
479 | r = kvm_read_guest_atomic(vcpu->kvm, pte_gpa, &pt, | 483 | if (r || is_present_pte(pt[j])) |
480 | sizeof(pt_element_t)); | 484 | sp->spt[i+j] = shadow_trap_nonpresent_pte; |
481 | if (r || is_present_pte(pt)) | 485 | else |
482 | sp->spt[i] = shadow_trap_nonpresent_pte; | 486 | sp->spt[i+j] = shadow_notrap_nonpresent_pte; |
483 | else | ||
484 | sp->spt[i] = shadow_notrap_nonpresent_pte; | ||
485 | } | 487 | } |
486 | } | 488 | } |
487 | 489 | ||