aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kvm/mmu.c26
1 files changed, 13 insertions, 13 deletions
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index b6e4cda77047..f85d9953a620 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -250,6 +250,15 @@ static int is_rmap_spte(u64 pte)
250 return is_shadow_present_pte(pte); 250 return is_shadow_present_pte(pte);
251} 251}
252 252
253static int is_last_spte(u64 pte, int level)
254{
255 if (level == PT_PAGE_TABLE_LEVEL)
256 return 1;
257 if (level == PT_DIRECTORY_LEVEL && is_large_pte(pte))
258 return 1;
259 return 0;
260}
261
253static pfn_t spte_to_pfn(u64 pte) 262static pfn_t spte_to_pfn(u64 pte)
254{ 263{
255 return (pte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT; 264 return (pte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT;
@@ -1313,25 +1322,17 @@ static void kvm_mmu_page_unlink_children(struct kvm *kvm,
1313 1322
1314 pt = sp->spt; 1323 pt = sp->spt;
1315 1324
1316 if (sp->role.level == PT_PAGE_TABLE_LEVEL) {
1317 for (i = 0; i < PT64_ENT_PER_PAGE; ++i) {
1318 if (is_shadow_present_pte(pt[i]))
1319 rmap_remove(kvm, &pt[i]);
1320 pt[i] = shadow_trap_nonpresent_pte;
1321 }
1322 return;
1323 }
1324
1325 for (i = 0; i < PT64_ENT_PER_PAGE; ++i) { 1325 for (i = 0; i < PT64_ENT_PER_PAGE; ++i) {
1326 ent = pt[i]; 1326 ent = pt[i];
1327 1327
1328 if (is_shadow_present_pte(ent)) { 1328 if (is_shadow_present_pte(ent)) {
1329 if (!is_large_pte(ent)) { 1329 if (!is_last_spte(ent, sp->role.level)) {
1330 ent &= PT64_BASE_ADDR_MASK; 1330 ent &= PT64_BASE_ADDR_MASK;
1331 mmu_page_remove_parent_pte(page_header(ent), 1331 mmu_page_remove_parent_pte(page_header(ent),
1332 &pt[i]); 1332 &pt[i]);
1333 } else { 1333 } else {
1334 --kvm->stat.lpages; 1334 if (is_large_pte(ent))
1335 --kvm->stat.lpages;
1335 rmap_remove(kvm, &pt[i]); 1336 rmap_remove(kvm, &pt[i]);
1336 } 1337 }
1337 } 1338 }
@@ -2381,8 +2382,7 @@ static void mmu_pte_write_zap_pte(struct kvm_vcpu *vcpu,
2381 2382
2382 pte = *spte; 2383 pte = *spte;
2383 if (is_shadow_present_pte(pte)) { 2384 if (is_shadow_present_pte(pte)) {
2384 if (sp->role.level == PT_PAGE_TABLE_LEVEL || 2385 if (is_last_spte(pte, sp->role.level))
2385 is_large_pte(pte))
2386 rmap_remove(vcpu->kvm, spte); 2386 rmap_remove(vcpu->kvm, spte);
2387 else { 2387 else {
2388 child = page_header(pte & PT64_BASE_ADDR_MASK); 2388 child = page_header(pte & PT64_BASE_ADDR_MASK);