diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kvm/mmu.c | 23 | ||||
-rw-r--r-- | arch/x86/kvm/paging_tmpl.h | 7 |
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, | |||
1329 | static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu, | 1329 | static 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 | ||
1347 | static bool need_remote_flush(u64 old, u64 new) | 1346 | static 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 | ||
245 | static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page, | 245 | static 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) |