diff options
author | Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> | 2010-08-22 07:13:33 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-10-24 04:51:28 -0400 |
commit | 189be38db3dde12699a8b9dc22d33e8c95efe110 (patch) | |
tree | 49896be03f57d6a4df979fe0649b590ef3d07a18 | |
parent | 957ed9effd80b04482cbdce8c95bdf803a656b94 (diff) |
KVM: MMU: combine guest pte read between fetch and pte prefetch
Combine guest pte read between guest pte check in the fetch path and pte prefetch
Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r-- | arch/x86/kvm/paging_tmpl.h | 40 |
1 files changed, 21 insertions, 19 deletions
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 872ff265c91e..a4e8389df2ad 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h | |||
@@ -67,6 +67,7 @@ struct guest_walker { | |||
67 | int level; | 67 | int level; |
68 | gfn_t table_gfn[PT_MAX_FULL_LEVELS]; | 68 | gfn_t table_gfn[PT_MAX_FULL_LEVELS]; |
69 | pt_element_t ptes[PT_MAX_FULL_LEVELS]; | 69 | pt_element_t ptes[PT_MAX_FULL_LEVELS]; |
70 | pt_element_t prefetch_ptes[PTE_PREFETCH_NUM]; | ||
70 | gpa_t pte_gpa[PT_MAX_FULL_LEVELS]; | 71 | gpa_t pte_gpa[PT_MAX_FULL_LEVELS]; |
71 | unsigned pt_access; | 72 | unsigned pt_access; |
72 | unsigned pte_access; | 73 | unsigned pte_access; |
@@ -302,21 +303,33 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp, | |||
302 | static bool FNAME(gpte_changed)(struct kvm_vcpu *vcpu, | 303 | static bool FNAME(gpte_changed)(struct kvm_vcpu *vcpu, |
303 | struct guest_walker *gw, int level) | 304 | struct guest_walker *gw, int level) |
304 | { | 305 | { |
305 | int r; | ||
306 | pt_element_t curr_pte; | 306 | pt_element_t curr_pte; |
307 | 307 | gpa_t base_gpa, pte_gpa = gw->pte_gpa[level - 1]; | |
308 | r = kvm_read_guest_atomic(vcpu->kvm, gw->pte_gpa[level - 1], | 308 | u64 mask; |
309 | int r, index; | ||
310 | |||
311 | if (level == PT_PAGE_TABLE_LEVEL) { | ||
312 | mask = PTE_PREFETCH_NUM * sizeof(pt_element_t) - 1; | ||
313 | base_gpa = pte_gpa & ~mask; | ||
314 | index = (pte_gpa - base_gpa) / sizeof(pt_element_t); | ||
315 | |||
316 | r = kvm_read_guest_atomic(vcpu->kvm, base_gpa, | ||
317 | gw->prefetch_ptes, sizeof(gw->prefetch_ptes)); | ||
318 | curr_pte = gw->prefetch_ptes[index]; | ||
319 | } else | ||
320 | r = kvm_read_guest_atomic(vcpu->kvm, pte_gpa, | ||
309 | &curr_pte, sizeof(curr_pte)); | 321 | &curr_pte, sizeof(curr_pte)); |
322 | |||
310 | return r || curr_pte != gw->ptes[level - 1]; | 323 | return r || curr_pte != gw->ptes[level - 1]; |
311 | } | 324 | } |
312 | 325 | ||
313 | static void FNAME(pte_prefetch)(struct kvm_vcpu *vcpu, u64 *sptep) | 326 | static void FNAME(pte_prefetch)(struct kvm_vcpu *vcpu, struct guest_walker *gw, |
327 | u64 *sptep) | ||
314 | { | 328 | { |
315 | struct kvm_mmu_page *sp; | 329 | struct kvm_mmu_page *sp; |
316 | pt_element_t gptep[PTE_PREFETCH_NUM]; | 330 | pt_element_t *gptep = gw->prefetch_ptes; |
317 | gpa_t first_pte_gpa; | ||
318 | int offset = 0, i; | ||
319 | u64 *spte; | 331 | u64 *spte; |
332 | int i; | ||
320 | 333 | ||
321 | sp = page_header(__pa(sptep)); | 334 | sp = page_header(__pa(sptep)); |
322 | 335 | ||
@@ -327,17 +340,6 @@ static void FNAME(pte_prefetch)(struct kvm_vcpu *vcpu, u64 *sptep) | |||
327 | return __direct_pte_prefetch(vcpu, sp, sptep); | 340 | return __direct_pte_prefetch(vcpu, sp, sptep); |
328 | 341 | ||
329 | i = (sptep - sp->spt) & ~(PTE_PREFETCH_NUM - 1); | 342 | i = (sptep - sp->spt) & ~(PTE_PREFETCH_NUM - 1); |
330 | |||
331 | if (PTTYPE == 32) | ||
332 | offset = sp->role.quadrant << PT64_LEVEL_BITS; | ||
333 | |||
334 | first_pte_gpa = gfn_to_gpa(sp->gfn) + | ||
335 | (offset + i) * sizeof(pt_element_t); | ||
336 | |||
337 | if (kvm_read_guest_atomic(vcpu->kvm, first_pte_gpa, gptep, | ||
338 | sizeof(gptep)) < 0) | ||
339 | return; | ||
340 | |||
341 | spte = sp->spt + i; | 343 | spte = sp->spt + i; |
342 | 344 | ||
343 | for (i = 0; i < PTE_PREFETCH_NUM; i++, spte++) { | 345 | for (i = 0; i < PTE_PREFETCH_NUM; i++, spte++) { |
@@ -462,7 +464,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, | |||
462 | mmu_set_spte(vcpu, it.sptep, access, gw->pte_access & access, | 464 | mmu_set_spte(vcpu, it.sptep, access, gw->pte_access & access, |
463 | user_fault, write_fault, dirty, ptwrite, it.level, | 465 | user_fault, write_fault, dirty, ptwrite, it.level, |
464 | gw->gfn, pfn, false, true); | 466 | gw->gfn, pfn, false, true); |
465 | FNAME(pte_prefetch)(vcpu, it.sptep); | 467 | FNAME(pte_prefetch)(vcpu, gw, it.sptep); |
466 | 468 | ||
467 | return it.sptep; | 469 | return it.sptep; |
468 | 470 | ||