diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kvm/mmu.c | 26 |
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 | ||
253 | static 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 | |||
253 | static pfn_t spte_to_pfn(u64 pte) | 262 | static 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); |