aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kvm/paging_tmpl.h40
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,
302static bool FNAME(gpte_changed)(struct kvm_vcpu *vcpu, 303static 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
313static void FNAME(pte_prefetch)(struct kvm_vcpu *vcpu, u64 *sptep) 326static 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