aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kvm/mmu.c23
-rw-r--r--arch/x86/kvm/paging_tmpl.h7
2 files changed, 18 insertions, 12 deletions
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index e55af12e11b7..28f9a44060cc 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -1329,8 +1329,7 @@ static void mmu_pte_write_zap_pte(struct kvm_vcpu *vcpu,
1329static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu, 1329static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu,
1330 struct kvm_mmu_page *sp, 1330 struct kvm_mmu_page *sp,
1331 u64 *spte, 1331 u64 *spte,
1332 const void *new, int bytes, 1332 const void *new)
1333 int offset_in_pte)
1334{ 1333{
1335 if (sp->role.level != PT_PAGE_TABLE_LEVEL) { 1334 if (sp->role.level != PT_PAGE_TABLE_LEVEL) {
1336 ++vcpu->kvm->stat.mmu_pde_zapped; 1335 ++vcpu->kvm->stat.mmu_pde_zapped;
@@ -1339,9 +1338,9 @@ static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu,
1339 1338
1340 ++vcpu->kvm->stat.mmu_pte_updated; 1339 ++vcpu->kvm->stat.mmu_pte_updated;
1341 if (sp->role.glevels == PT32_ROOT_LEVEL) 1340 if (sp->role.glevels == PT32_ROOT_LEVEL)
1342 paging32_update_pte(vcpu, sp, spte, new, bytes, offset_in_pte); 1341 paging32_update_pte(vcpu, sp, spte, new);
1343 else 1342 else
1344 paging64_update_pte(vcpu, sp, spte, new, bytes, offset_in_pte); 1343 paging64_update_pte(vcpu, sp, spte, new);
1345} 1344}
1346 1345
1347static bool need_remote_flush(u64 old, u64 new) 1346static bool need_remote_flush(u64 old, u64 new)
@@ -1423,7 +1422,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
1423 struct hlist_node *node, *n; 1422 struct hlist_node *node, *n;
1424 struct hlist_head *bucket; 1423 struct hlist_head *bucket;
1425 unsigned index; 1424 unsigned index;
1426 u64 entry; 1425 u64 entry, gentry;
1427 u64 *spte; 1426 u64 *spte;
1428 unsigned offset = offset_in_page(gpa); 1427 unsigned offset = offset_in_page(gpa);
1429 unsigned pte_size; 1428 unsigned pte_size;
@@ -1433,6 +1432,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
1433 int level; 1432 int level;
1434 int flooded = 0; 1433 int flooded = 0;
1435 int npte; 1434 int npte;
1435 int r;
1436 1436
1437 pgprintk("%s: gpa %llx bytes %d\n", __FUNCTION__, gpa, bytes); 1437 pgprintk("%s: gpa %llx bytes %d\n", __FUNCTION__, gpa, bytes);
1438 mmu_guess_page_from_pte_write(vcpu, gpa, new, bytes); 1438 mmu_guess_page_from_pte_write(vcpu, gpa, new, bytes);
@@ -1496,11 +1496,20 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
1496 continue; 1496 continue;
1497 } 1497 }
1498 spte = &sp->spt[page_offset / sizeof(*spte)]; 1498 spte = &sp->spt[page_offset / sizeof(*spte)];
1499 if ((gpa & (pte_size - 1)) || (bytes < pte_size)) {
1500 gentry = 0;
1501 r = kvm_read_guest_atomic(vcpu->kvm,
1502 gpa & ~(u64)(pte_size - 1),
1503 &gentry, pte_size);
1504 new = (const void *)&gentry;
1505 if (r < 0)
1506 new = NULL;
1507 }
1499 while (npte--) { 1508 while (npte--) {
1500 entry = *spte; 1509 entry = *spte;
1501 mmu_pte_write_zap_pte(vcpu, sp, spte); 1510 mmu_pte_write_zap_pte(vcpu, sp, spte);
1502 mmu_pte_write_new_pte(vcpu, sp, spte, new, bytes, 1511 if (new)
1503 page_offset & (pte_size - 1)); 1512 mmu_pte_write_new_pte(vcpu, sp, spte, new);
1504 mmu_pte_write_flush_tlb(vcpu, entry, *spte); 1513 mmu_pte_write_flush_tlb(vcpu, entry, *spte);
1505 ++spte; 1514 ++spte;
1506 } 1515 }
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index ecc0856268c4..c2fd2b96144f 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -243,8 +243,7 @@ err:
243} 243}
244 244
245static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page, 245static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page,
246 u64 *spte, const void *pte, int bytes, 246 u64 *spte, const void *pte)
247 int offset_in_pte)
248{ 247{
249 pt_element_t gpte; 248 pt_element_t gpte;
250 unsigned pte_access; 249 unsigned pte_access;
@@ -252,12 +251,10 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page,
252 251
253 gpte = *(const pt_element_t *)pte; 252 gpte = *(const pt_element_t *)pte;
254 if (~gpte & (PT_PRESENT_MASK | PT_ACCESSED_MASK)) { 253 if (~gpte & (PT_PRESENT_MASK | PT_ACCESSED_MASK)) {
255 if (!offset_in_pte && !is_present_pte(gpte)) 254 if (!is_present_pte(gpte))
256 set_shadow_pte(spte, shadow_notrap_nonpresent_pte); 255 set_shadow_pte(spte, shadow_notrap_nonpresent_pte);
257 return; 256 return;
258 } 257 }
259 if (bytes < sizeof(pt_element_t))
260 return;
261 pgprintk("%s: gpte %llx spte %p\n", __FUNCTION__, (u64)gpte, spte); 258 pgprintk("%s: gpte %llx spte %p\n", __FUNCTION__, (u64)gpte, spte);
262 pte_access = page->role.access & FNAME(gpte_access)(vcpu, gpte); 259 pte_access = page->role.access & FNAME(gpte_access)(vcpu, gpte);
263 if (gpte_to_gfn(gpte) != vcpu->arch.update_pte.gfn) 260 if (gpte_to_gfn(gpte) != vcpu->arch.update_pte.gfn)