aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMarcelo Tosatti <mtosatti@redhat.com>2009-06-10 11:27:03 -0400
committerAvi Kivity <avi@redhat.com>2009-09-10 01:32:53 -0400
commit776e6633363b5616be6fa4493a8b70ef8e2ea04b (patch)
tree07c0c2547f681330b600f82e860d3e74192532d5 /arch
parent3f5d18a96577fd78277e08c467041573b9a65eaf (diff)
KVM: MMU: introduce is_last_spte helper
Hiding some of the last largepage / level interaction (which is useful for gbpages and for zero based levels). Also merge the PT_PAGE_TABLE_LEVEL clearing loop in unlink_children. Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch')
-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);