aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorXiao Guangrong <xiaoguangrong@cn.fujitsu.com>2010-05-24 03:41:33 -0400
committerAvi Kivity <avi@redhat.com>2010-08-01 03:35:52 -0400
commit9f1a122f970dbef5ba3496587f39df5c1853083f (patch)
tree243f14f5f1d85a6902ac5ca25b6b3ff1aa6a520c /arch
parent9cf5cf5ad43b293581e5b87678ea5783c06d1a41 (diff)
KVM: MMU: allow more page become unsync at getting sp time
Allow more page become asynchronous at getting sp time, if need create new shadow page for gfn but it not allow unsync(level > 1), we should unsync all gfn's unsync page Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kvm/mmu.c47
1 files changed, 37 insertions, 10 deletions
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index ba119dae890e..07673487fd5d 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -1220,6 +1220,35 @@ static int kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
1220 return __kvm_sync_page(vcpu, sp, true); 1220 return __kvm_sync_page(vcpu, sp, true);
1221} 1221}
1222 1222
1223/* @gfn should be write-protected at the call site */
1224static void kvm_sync_pages(struct kvm_vcpu *vcpu, gfn_t gfn)
1225{
1226 struct hlist_head *bucket;
1227 struct kvm_mmu_page *s;
1228 struct hlist_node *node, *n;
1229 unsigned index;
1230 bool flush = false;
1231
1232 index = kvm_page_table_hashfn(gfn);
1233 bucket = &vcpu->kvm->arch.mmu_page_hash[index];
1234 hlist_for_each_entry_safe(s, node, n, bucket, hash_link) {
1235 if (s->gfn != gfn || !s->unsync || s->role.invalid)
1236 continue;
1237
1238 WARN_ON(s->role.level != PT_PAGE_TABLE_LEVEL);
1239 if ((s->role.cr4_pae != !!is_pae(vcpu)) ||
1240 (vcpu->arch.mmu.sync_page(vcpu, s))) {
1241 kvm_mmu_zap_page(vcpu->kvm, s);
1242 continue;
1243 }
1244 kvm_unlink_unsync_page(vcpu->kvm, s);
1245 flush = true;
1246 }
1247
1248 if (flush)
1249 kvm_mmu_flush_tlb(vcpu);
1250}
1251
1223struct mmu_page_path { 1252struct mmu_page_path {
1224 struct kvm_mmu_page *parent[PT64_ROOT_LEVEL-1]; 1253 struct kvm_mmu_page *parent[PT64_ROOT_LEVEL-1];
1225 unsigned int idx[PT64_ROOT_LEVEL-1]; 1254 unsigned int idx[PT64_ROOT_LEVEL-1];
@@ -1318,8 +1347,9 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
1318 unsigned index; 1347 unsigned index;
1319 unsigned quadrant; 1348 unsigned quadrant;
1320 struct hlist_head *bucket; 1349 struct hlist_head *bucket;
1321 struct kvm_mmu_page *sp, *unsync_sp = NULL; 1350 struct kvm_mmu_page *sp;
1322 struct hlist_node *node, *tmp; 1351 struct hlist_node *node, *tmp;
1352 bool need_sync = false;
1323 1353
1324 role = vcpu->arch.mmu.base_role; 1354 role = vcpu->arch.mmu.base_role;
1325 role.level = level; 1355 role.level = level;
@@ -1336,17 +1366,14 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
1336 bucket = &vcpu->kvm->arch.mmu_page_hash[index]; 1366 bucket = &vcpu->kvm->arch.mmu_page_hash[index];
1337 hlist_for_each_entry_safe(sp, node, tmp, bucket, hash_link) 1367 hlist_for_each_entry_safe(sp, node, tmp, bucket, hash_link)
1338 if (sp->gfn == gfn) { 1368 if (sp->gfn == gfn) {
1339 if (sp->unsync) 1369 if (!need_sync && sp->unsync)
1340 unsync_sp = sp; 1370 need_sync = true;
1341 1371
1342 if (sp->role.word != role.word) 1372 if (sp->role.word != role.word)
1343 continue; 1373 continue;
1344 1374
1345 if (!direct && unsync_sp && 1375 if (sp->unsync && kvm_sync_page_transient(vcpu, sp))
1346 kvm_sync_page_transient(vcpu, unsync_sp)) {
1347 unsync_sp = NULL;
1348 break; 1376 break;
1349 }
1350 1377
1351 mmu_page_add_parent_pte(vcpu, sp, parent_pte); 1378 mmu_page_add_parent_pte(vcpu, sp, parent_pte);
1352 if (sp->unsync_children) { 1379 if (sp->unsync_children) {
@@ -1358,9 +1385,6 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
1358 trace_kvm_mmu_get_page(sp, false); 1385 trace_kvm_mmu_get_page(sp, false);
1359 return sp; 1386 return sp;
1360 } 1387 }
1361 if (!direct && unsync_sp)
1362 kvm_sync_page(vcpu, unsync_sp);
1363
1364 ++vcpu->kvm->stat.mmu_cache_miss; 1388 ++vcpu->kvm->stat.mmu_cache_miss;
1365 sp = kvm_mmu_alloc_page(vcpu, parent_pte); 1389 sp = kvm_mmu_alloc_page(vcpu, parent_pte);
1366 if (!sp) 1390 if (!sp)
@@ -1371,6 +1395,9 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
1371 if (!direct) { 1395 if (!direct) {
1372 if (rmap_write_protect(vcpu->kvm, gfn)) 1396 if (rmap_write_protect(vcpu->kvm, gfn))
1373 kvm_flush_remote_tlbs(vcpu->kvm); 1397 kvm_flush_remote_tlbs(vcpu->kvm);
1398 if (level > PT_PAGE_TABLE_LEVEL && need_sync)
1399 kvm_sync_pages(vcpu, gfn);
1400
1374 account_shadowed(vcpu->kvm, gfn); 1401 account_shadowed(vcpu->kvm, gfn);
1375 } 1402 }
1376 if (shadow_trap_nonpresent_pte != shadow_notrap_nonpresent_pte) 1403 if (shadow_trap_nonpresent_pte != shadow_notrap_nonpresent_pte)