diff options
| -rw-r--r-- | arch/x86/kvm/mmu.c | 210 | ||||
| -rw-r--r-- | arch/x86/kvm/paging_tmpl.h | 2 | ||||
| -rw-r--r-- | arch/x86/kvm/x86.c | 3 | ||||
| -rw-r--r-- | include/asm-x86/kvm_host.h | 3 | ||||
| -rw-r--r-- | include/linux/kvm_host.h | 1 |
5 files changed, 201 insertions, 18 deletions
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 57c7580e7f98..d88659ae7778 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
| @@ -147,6 +147,10 @@ struct kvm_shadow_walk { | |||
| 147 | u64 addr, u64 *spte, int level); | 147 | u64 addr, u64 *spte, int level); |
| 148 | }; | 148 | }; |
| 149 | 149 | ||
| 150 | struct kvm_unsync_walk { | ||
| 151 | int (*entry) (struct kvm_mmu_page *sp, struct kvm_unsync_walk *walk); | ||
| 152 | }; | ||
| 153 | |||
| 150 | typedef int (*mmu_parent_walk_fn) (struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp); | 154 | typedef int (*mmu_parent_walk_fn) (struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp); |
| 151 | 155 | ||
| 152 | static struct kmem_cache *pte_chain_cache; | 156 | static struct kmem_cache *pte_chain_cache; |
| @@ -654,8 +658,6 @@ static void rmap_write_protect(struct kvm *kvm, u64 gfn) | |||
| 654 | 658 | ||
| 655 | if (write_protected) | 659 | if (write_protected) |
| 656 | kvm_flush_remote_tlbs(kvm); | 660 | kvm_flush_remote_tlbs(kvm); |
| 657 | |||
| 658 | account_shadowed(kvm, gfn); | ||
| 659 | } | 661 | } |
| 660 | 662 | ||
| 661 | static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp) | 663 | static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp) |
| @@ -908,6 +910,41 @@ static void nonpaging_invlpg(struct kvm_vcpu *vcpu, gva_t gva) | |||
| 908 | { | 910 | { |
| 909 | } | 911 | } |
| 910 | 912 | ||
| 913 | static int mmu_unsync_walk(struct kvm_mmu_page *sp, | ||
| 914 | struct kvm_unsync_walk *walker) | ||
| 915 | { | ||
| 916 | int i, ret; | ||
| 917 | |||
| 918 | if (!sp->unsync_children) | ||
| 919 | return 0; | ||
| 920 | |||
| 921 | for (i = 0; i < PT64_ENT_PER_PAGE; ++i) { | ||
| 922 | u64 ent = sp->spt[i]; | ||
| 923 | |||
| 924 | if (is_shadow_present_pte(ent)) { | ||
| 925 | struct kvm_mmu_page *child; | ||
| 926 | child = page_header(ent & PT64_BASE_ADDR_MASK); | ||
| 927 | |||
| 928 | if (child->unsync_children) { | ||
| 929 | ret = mmu_unsync_walk(child, walker); | ||
| 930 | if (ret) | ||
| 931 | return ret; | ||
| 932 | } | ||
| 933 | |||
| 934 | if (child->unsync) { | ||
| 935 | ret = walker->entry(child, walker); | ||
| 936 | if (ret) | ||
| 937 | return ret; | ||
| 938 | } | ||
| 939 | } | ||
| 940 | } | ||
| 941 | |||
| 942 | if (i == PT64_ENT_PER_PAGE) | ||
| 943 | sp->unsync_children = 0; | ||
| 944 | |||
| 945 | return 0; | ||
| 946 | } | ||
| 947 | |||
| 911 | static struct kvm_mmu_page *kvm_mmu_lookup_page(struct kvm *kvm, gfn_t gfn) | 948 | static struct kvm_mmu_page *kvm_mmu_lookup_page(struct kvm *kvm, gfn_t gfn) |
| 912 | { | 949 | { |
| 913 | unsigned index; | 950 | unsigned index; |
| @@ -928,6 +965,59 @@ static struct kvm_mmu_page *kvm_mmu_lookup_page(struct kvm *kvm, gfn_t gfn) | |||
| 928 | return NULL; | 965 | return NULL; |
| 929 | } | 966 | } |
| 930 | 967 | ||
| 968 | static void kvm_unlink_unsync_page(struct kvm *kvm, struct kvm_mmu_page *sp) | ||
| 969 | { | ||
| 970 | WARN_ON(!sp->unsync); | ||
| 971 | sp->unsync = 0; | ||
| 972 | --kvm->stat.mmu_unsync; | ||
| 973 | } | ||
| 974 | |||
| 975 | static int kvm_mmu_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp); | ||
| 976 | |||
| 977 | static int kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) | ||
| 978 | { | ||
| 979 | if (sp->role.glevels != vcpu->arch.mmu.root_level) { | ||
| 980 | kvm_mmu_zap_page(vcpu->kvm, sp); | ||
| 981 | return 1; | ||
| 982 | } | ||
| 983 | |||
| 984 | rmap_write_protect(vcpu->kvm, sp->gfn); | ||
| 985 | if (vcpu->arch.mmu.sync_page(vcpu, sp)) { | ||
| 986 | kvm_mmu_zap_page(vcpu->kvm, sp); | ||
| 987 | return 1; | ||
| 988 | } | ||
| 989 | |||
| 990 | kvm_mmu_flush_tlb(vcpu); | ||
| 991 | kvm_unlink_unsync_page(vcpu->kvm, sp); | ||
| 992 | return 0; | ||
| 993 | } | ||
| 994 | |||
| 995 | struct sync_walker { | ||
| 996 | struct kvm_vcpu *vcpu; | ||
| 997 | struct kvm_unsync_walk walker; | ||
| 998 | }; | ||
| 999 | |||
| 1000 | static int mmu_sync_fn(struct kvm_mmu_page *sp, struct kvm_unsync_walk *walk) | ||
| 1001 | { | ||
| 1002 | struct sync_walker *sync_walk = container_of(walk, struct sync_walker, | ||
| 1003 | walker); | ||
| 1004 | struct kvm_vcpu *vcpu = sync_walk->vcpu; | ||
| 1005 | |||
| 1006 | kvm_sync_page(vcpu, sp); | ||
| 1007 | return (need_resched() || spin_needbreak(&vcpu->kvm->mmu_lock)); | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | static void mmu_sync_children(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) | ||
| 1011 | { | ||
| 1012 | struct sync_walker walker = { | ||
| 1013 | .walker = { .entry = mmu_sync_fn, }, | ||
| 1014 | .vcpu = vcpu, | ||
| 1015 | }; | ||
| 1016 | |||
| 1017 | while (mmu_unsync_walk(sp, &walker.walker)) | ||
| 1018 | cond_resched_lock(&vcpu->kvm->mmu_lock); | ||
| 1019 | } | ||
| 1020 | |||
| 931 | static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, | 1021 | static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, |
| 932 | gfn_t gfn, | 1022 | gfn_t gfn, |
| 933 | gva_t gaddr, | 1023 | gva_t gaddr, |
| @@ -941,7 +1031,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, | |||
| 941 | unsigned quadrant; | 1031 | unsigned quadrant; |
| 942 | struct hlist_head *bucket; | 1032 | struct hlist_head *bucket; |
| 943 | struct kvm_mmu_page *sp; | 1033 | struct kvm_mmu_page *sp; |
| 944 | struct hlist_node *node; | 1034 | struct hlist_node *node, *tmp; |
| 945 | 1035 | ||
| 946 | role.word = 0; | 1036 | role.word = 0; |
| 947 | role.glevels = vcpu->arch.mmu.root_level; | 1037 | role.glevels = vcpu->arch.mmu.root_level; |
| @@ -957,8 +1047,18 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, | |||
| 957 | gfn, role.word); | 1047 | gfn, role.word); |
| 958 | index = kvm_page_table_hashfn(gfn); | 1048 | index = kvm_page_table_hashfn(gfn); |
| 959 | bucket = &vcpu->kvm->arch.mmu_page_hash[index]; | 1049 | bucket = &vcpu->kvm->arch.mmu_page_hash[index]; |
| 960 | hlist_for_each_entry(sp, node, bucket, hash_link) | 1050 | hlist_for_each_entry_safe(sp, node, tmp, bucket, hash_link) |
| 961 | if (sp->gfn == gfn && sp->role.word == role.word) { | 1051 | if (sp->gfn == gfn) { |
| 1052 | if (sp->unsync) | ||
| 1053 | if (kvm_sync_page(vcpu, sp)) | ||
| 1054 | continue; | ||
| 1055 | |||
| 1056 | if (sp->role.word != role.word) | ||
| 1057 | continue; | ||
| 1058 | |||
| 1059 | if (sp->unsync_children) | ||
| 1060 | set_bit(KVM_REQ_MMU_SYNC, &vcpu->requests); | ||
| 1061 | |||
| 962 | mmu_page_add_parent_pte(vcpu, sp, parent_pte); | 1062 | mmu_page_add_parent_pte(vcpu, sp, parent_pte); |
| 963 | pgprintk("%s: found\n", __func__); | 1063 | pgprintk("%s: found\n", __func__); |
| 964 | return sp; | 1064 | return sp; |
| @@ -971,8 +1071,10 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, | |||
| 971 | sp->gfn = gfn; | 1071 | sp->gfn = gfn; |
| 972 | sp->role = role; | 1072 | sp->role = role; |
| 973 | hlist_add_head(&sp->hash_link, bucket); | 1073 | hlist_add_head(&sp->hash_link, bucket); |
| 974 | if (!metaphysical) | 1074 | if (!metaphysical) { |
| 975 | rmap_write_protect(vcpu->kvm, gfn); | 1075 | rmap_write_protect(vcpu->kvm, gfn); |
| 1076 | account_shadowed(vcpu->kvm, gfn); | ||
| 1077 | } | ||
| 976 | if (shadow_trap_nonpresent_pte != shadow_notrap_nonpresent_pte) | 1078 | if (shadow_trap_nonpresent_pte != shadow_notrap_nonpresent_pte) |
| 977 | vcpu->arch.mmu.prefetch_page(vcpu, sp); | 1079 | vcpu->arch.mmu.prefetch_page(vcpu, sp); |
| 978 | else | 1080 | else |
| @@ -1078,14 +1180,47 @@ static void kvm_mmu_unlink_parents(struct kvm *kvm, struct kvm_mmu_page *sp) | |||
| 1078 | } | 1180 | } |
| 1079 | } | 1181 | } |
| 1080 | 1182 | ||
| 1183 | struct zap_walker { | ||
| 1184 | struct kvm_unsync_walk walker; | ||
| 1185 | struct kvm *kvm; | ||
| 1186 | int zapped; | ||
| 1187 | }; | ||
| 1188 | |||
| 1189 | static int mmu_zap_fn(struct kvm_mmu_page *sp, struct kvm_unsync_walk *walk) | ||
| 1190 | { | ||
| 1191 | struct zap_walker *zap_walk = container_of(walk, struct zap_walker, | ||
| 1192 | walker); | ||
| 1193 | kvm_mmu_zap_page(zap_walk->kvm, sp); | ||
| 1194 | zap_walk->zapped = 1; | ||
| 1195 | return 0; | ||
| 1196 | } | ||
| 1197 | |||
| 1198 | static int mmu_zap_unsync_children(struct kvm *kvm, struct kvm_mmu_page *sp) | ||
| 1199 | { | ||
| 1200 | struct zap_walker walker = { | ||
| 1201 | .walker = { .entry = mmu_zap_fn, }, | ||
| 1202 | .kvm = kvm, | ||
| 1203 | .zapped = 0, | ||
| 1204 | }; | ||
| 1205 | |||
| 1206 | if (sp->role.level == PT_PAGE_TABLE_LEVEL) | ||
| 1207 | return 0; | ||
| 1208 | mmu_unsync_walk(sp, &walker.walker); | ||
| 1209 | return walker.zapped; | ||
| 1210 | } | ||
| 1211 | |||
| 1081 | static int kvm_mmu_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp) | 1212 | static int kvm_mmu_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp) |
| 1082 | { | 1213 | { |
| 1214 | int ret; | ||
| 1083 | ++kvm->stat.mmu_shadow_zapped; | 1215 | ++kvm->stat.mmu_shadow_zapped; |
| 1216 | ret = mmu_zap_unsync_children(kvm, sp); | ||
| 1084 | kvm_mmu_page_unlink_children(kvm, sp); | 1217 | kvm_mmu_page_unlink_children(kvm, sp); |
| 1085 | kvm_mmu_unlink_parents(kvm, sp); | 1218 | kvm_mmu_unlink_parents(kvm, sp); |
| 1086 | kvm_flush_remote_tlbs(kvm); | 1219 | kvm_flush_remote_tlbs(kvm); |
| 1087 | if (!sp->role.invalid && !sp->role.metaphysical) | 1220 | if (!sp->role.invalid && !sp->role.metaphysical) |
| 1088 | unaccount_shadowed(kvm, sp->gfn); | 1221 | unaccount_shadowed(kvm, sp->gfn); |
| 1222 | if (sp->unsync) | ||
| 1223 | kvm_unlink_unsync_page(kvm, sp); | ||
| 1089 | if (!sp->root_count) { | 1224 | if (!sp->root_count) { |
| 1090 | hlist_del(&sp->hash_link); | 1225 | hlist_del(&sp->hash_link); |
| 1091 | kvm_mmu_free_page(kvm, sp); | 1226 | kvm_mmu_free_page(kvm, sp); |
| @@ -1095,7 +1230,7 @@ static int kvm_mmu_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp) | |||
| 1095 | kvm_reload_remote_mmus(kvm); | 1230 | kvm_reload_remote_mmus(kvm); |
| 1096 | } | 1231 | } |
| 1097 | kvm_mmu_reset_last_pte_updated(kvm); | 1232 | kvm_mmu_reset_last_pte_updated(kvm); |
| 1098 | return 0; | 1233 | return ret; |
| 1099 | } | 1234 | } |
| 1100 | 1235 | ||
| 1101 | /* | 1236 | /* |
| @@ -1201,10 +1336,58 @@ struct page *gva_to_page(struct kvm_vcpu *vcpu, gva_t gva) | |||
| 1201 | return page; | 1336 | return page; |
| 1202 | } | 1337 | } |
| 1203 | 1338 | ||
| 1339 | static int unsync_walk_fn(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) | ||
| 1340 | { | ||
| 1341 | sp->unsync_children = 1; | ||
| 1342 | return 1; | ||
| 1343 | } | ||
| 1344 | |||
| 1345 | static int kvm_unsync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) | ||
| 1346 | { | ||
| 1347 | unsigned index; | ||
| 1348 | struct hlist_head *bucket; | ||
| 1349 | struct kvm_mmu_page *s; | ||
| 1350 | struct hlist_node *node, *n; | ||
| 1351 | |||
| 1352 | index = kvm_page_table_hashfn(sp->gfn); | ||
| 1353 | bucket = &vcpu->kvm->arch.mmu_page_hash[index]; | ||
| 1354 | /* don't unsync if pagetable is shadowed with multiple roles */ | ||
| 1355 | hlist_for_each_entry_safe(s, node, n, bucket, hash_link) { | ||
| 1356 | if (s->gfn != sp->gfn || s->role.metaphysical) | ||
| 1357 | continue; | ||
| 1358 | if (s->role.word != sp->role.word) | ||
| 1359 | return 1; | ||
| 1360 | } | ||
| 1361 | mmu_parent_walk(vcpu, sp, unsync_walk_fn); | ||
| 1362 | ++vcpu->kvm->stat.mmu_unsync; | ||
| 1363 | sp->unsync = 1; | ||
| 1364 | mmu_convert_notrap(sp); | ||
| 1365 | return 0; | ||
| 1366 | } | ||
| 1367 | |||
| 1368 | static int mmu_need_write_protect(struct kvm_vcpu *vcpu, gfn_t gfn, | ||
| 1369 | bool can_unsync) | ||
| 1370 | { | ||
| 1371 | struct kvm_mmu_page *shadow; | ||
| 1372 | |||
| 1373 | shadow = kvm_mmu_lookup_page(vcpu->kvm, gfn); | ||
| 1374 | if (shadow) { | ||
| 1375 | if (shadow->role.level != PT_PAGE_TABLE_LEVEL) | ||
| 1376 | return 1; | ||
| 1377 | if (shadow->unsync) | ||
| 1378 | return 0; | ||
| 1379 | if (can_unsync) | ||
| 1380 | return kvm_unsync_page(vcpu, shadow); | ||
| 1381 | return 1; | ||
| 1382 | } | ||
| 1383 | return 0; | ||
| 1384 | } | ||
| 1385 | |||
| 1204 | static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, | 1386 | static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, |
| 1205 | unsigned pte_access, int user_fault, | 1387 | unsigned pte_access, int user_fault, |
| 1206 | int write_fault, int dirty, int largepage, | 1388 | int write_fault, int dirty, int largepage, |
| 1207 | gfn_t gfn, pfn_t pfn, bool speculative) | 1389 | gfn_t gfn, pfn_t pfn, bool speculative, |
| 1390 | bool can_unsync) | ||
| 1208 | { | 1391 | { |
| 1209 | u64 spte; | 1392 | u64 spte; |
| 1210 | int ret = 0; | 1393 | int ret = 0; |
| @@ -1231,7 +1414,6 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, | |||
| 1231 | 1414 | ||
| 1232 | if ((pte_access & ACC_WRITE_MASK) | 1415 | if ((pte_access & ACC_WRITE_MASK) |
| 1233 | || (write_fault && !is_write_protection(vcpu) && !user_fault)) { | 1416 | || (write_fault && !is_write_protection(vcpu) && !user_fault)) { |
| 1234 | struct kvm_mmu_page *shadow; | ||
| 1235 | 1417 | ||
| 1236 | if (largepage && has_wrprotected_page(vcpu->kvm, gfn)) { | 1418 | if (largepage && has_wrprotected_page(vcpu->kvm, gfn)) { |
| 1237 | ret = 1; | 1419 | ret = 1; |
| @@ -1241,8 +1423,7 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, | |||
| 1241 | 1423 | ||
| 1242 | spte |= PT_WRITABLE_MASK; | 1424 | spte |= PT_WRITABLE_MASK; |
| 1243 | 1425 | ||
| 1244 | shadow = kvm_mmu_lookup_page(vcpu->kvm, gfn); | 1426 | if (mmu_need_write_protect(vcpu, gfn, can_unsync)) { |
| 1245 | if (shadow) { | ||
| 1246 | pgprintk("%s: found shadow page for %lx, marking ro\n", | 1427 | pgprintk("%s: found shadow page for %lx, marking ro\n", |
| 1247 | __func__, gfn); | 1428 | __func__, gfn); |
| 1248 | ret = 1; | 1429 | ret = 1; |
| @@ -1260,7 +1441,6 @@ set_pte: | |||
| 1260 | return ret; | 1441 | return ret; |
| 1261 | } | 1442 | } |
| 1262 | 1443 | ||
| 1263 | |||
| 1264 | static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, | 1444 | static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, |
| 1265 | unsigned pt_access, unsigned pte_access, | 1445 | unsigned pt_access, unsigned pte_access, |
| 1266 | int user_fault, int write_fault, int dirty, | 1446 | int user_fault, int write_fault, int dirty, |
| @@ -1298,7 +1478,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, | |||
| 1298 | } | 1478 | } |
| 1299 | } | 1479 | } |
| 1300 | if (set_spte(vcpu, shadow_pte, pte_access, user_fault, write_fault, | 1480 | if (set_spte(vcpu, shadow_pte, pte_access, user_fault, write_fault, |
| 1301 | dirty, largepage, gfn, pfn, speculative)) { | 1481 | dirty, largepage, gfn, pfn, speculative, true)) { |
| 1302 | if (write_fault) | 1482 | if (write_fault) |
| 1303 | *ptwrite = 1; | 1483 | *ptwrite = 1; |
| 1304 | kvm_x86_ops->tlb_flush(vcpu); | 1484 | kvm_x86_ops->tlb_flush(vcpu); |
| @@ -1518,10 +1698,6 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu) | |||
| 1518 | vcpu->arch.mmu.root_hpa = __pa(vcpu->arch.mmu.pae_root); | 1698 | vcpu->arch.mmu.root_hpa = __pa(vcpu->arch.mmu.pae_root); |
| 1519 | } | 1699 | } |
| 1520 | 1700 | ||
| 1521 | static void mmu_sync_children(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) | ||
| 1522 | { | ||
| 1523 | } | ||
| 1524 | |||
| 1525 | static void mmu_sync_roots(struct kvm_vcpu *vcpu) | 1701 | static void mmu_sync_roots(struct kvm_vcpu *vcpu) |
| 1526 | { | 1702 | { |
| 1527 | int i; | 1703 | int i; |
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index dc169e8148b1..613ec9aa674a 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h | |||
| @@ -580,7 +580,7 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) | |||
| 580 | pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte); | 580 | pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte); |
| 581 | set_spte(vcpu, &sp->spt[i], pte_access, 0, 0, | 581 | set_spte(vcpu, &sp->spt[i], pte_access, 0, 0, |
| 582 | is_dirty_pte(gpte), 0, gfn, | 582 | is_dirty_pte(gpte), 0, gfn, |
| 583 | spte_to_pfn(sp->spt[i]), true); | 583 | spte_to_pfn(sp->spt[i]), true, false); |
| 584 | } | 584 | } |
| 585 | 585 | ||
| 586 | return !nr_present; | 586 | return !nr_present; |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index efee85ba07e5..1c5864ac0837 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
| @@ -101,6 +101,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { | |||
| 101 | { "mmu_flooded", VM_STAT(mmu_flooded) }, | 101 | { "mmu_flooded", VM_STAT(mmu_flooded) }, |
| 102 | { "mmu_recycled", VM_STAT(mmu_recycled) }, | 102 | { "mmu_recycled", VM_STAT(mmu_recycled) }, |
| 103 | { "mmu_cache_miss", VM_STAT(mmu_cache_miss) }, | 103 | { "mmu_cache_miss", VM_STAT(mmu_cache_miss) }, |
| 104 | { "mmu_unsync", VM_STAT(mmu_unsync) }, | ||
| 104 | { "remote_tlb_flush", VM_STAT(remote_tlb_flush) }, | 105 | { "remote_tlb_flush", VM_STAT(remote_tlb_flush) }, |
| 105 | { "largepages", VM_STAT(lpages) }, | 106 | { "largepages", VM_STAT(lpages) }, |
| 106 | { NULL } | 107 | { NULL } |
| @@ -3120,6 +3121,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
| 3120 | if (vcpu->requests) { | 3121 | if (vcpu->requests) { |
| 3121 | if (test_and_clear_bit(KVM_REQ_MIGRATE_TIMER, &vcpu->requests)) | 3122 | if (test_and_clear_bit(KVM_REQ_MIGRATE_TIMER, &vcpu->requests)) |
| 3122 | __kvm_migrate_timers(vcpu); | 3123 | __kvm_migrate_timers(vcpu); |
| 3124 | if (test_and_clear_bit(KVM_REQ_MMU_SYNC, &vcpu->requests)) | ||
| 3125 | kvm_mmu_sync_roots(vcpu); | ||
| 3123 | if (test_and_clear_bit(KVM_REQ_TLB_FLUSH, &vcpu->requests)) | 3126 | if (test_and_clear_bit(KVM_REQ_TLB_FLUSH, &vcpu->requests)) |
| 3124 | kvm_x86_ops->tlb_flush(vcpu); | 3127 | kvm_x86_ops->tlb_flush(vcpu); |
| 3125 | if (test_and_clear_bit(KVM_REQ_REPORT_TPR_ACCESS, | 3128 | if (test_and_clear_bit(KVM_REQ_REPORT_TPR_ACCESS, |
diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h index 8b935cc4c14b..7d36fcc02818 100644 --- a/include/asm-x86/kvm_host.h +++ b/include/asm-x86/kvm_host.h | |||
| @@ -195,6 +195,8 @@ struct kvm_mmu_page { | |||
| 195 | */ | 195 | */ |
| 196 | int multimapped; /* More than one parent_pte? */ | 196 | int multimapped; /* More than one parent_pte? */ |
| 197 | int root_count; /* Currently serving as active root */ | 197 | int root_count; /* Currently serving as active root */ |
| 198 | bool unsync; | ||
| 199 | bool unsync_children; | ||
| 198 | union { | 200 | union { |
| 199 | u64 *parent_pte; /* !multimapped */ | 201 | u64 *parent_pte; /* !multimapped */ |
| 200 | struct hlist_head parent_ptes; /* multimapped, kvm_pte_chain */ | 202 | struct hlist_head parent_ptes; /* multimapped, kvm_pte_chain */ |
| @@ -371,6 +373,7 @@ struct kvm_vm_stat { | |||
| 371 | u32 mmu_flooded; | 373 | u32 mmu_flooded; |
| 372 | u32 mmu_recycled; | 374 | u32 mmu_recycled; |
| 373 | u32 mmu_cache_miss; | 375 | u32 mmu_cache_miss; |
| 376 | u32 mmu_unsync; | ||
| 374 | u32 remote_tlb_flush; | 377 | u32 remote_tlb_flush; |
| 375 | u32 lpages; | 378 | u32 lpages; |
| 376 | }; | 379 | }; |
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 6252802c3cc0..73b7c52b9493 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #define KVM_REQ_TRIPLE_FAULT 4 | 35 | #define KVM_REQ_TRIPLE_FAULT 4 |
| 36 | #define KVM_REQ_PENDING_TIMER 5 | 36 | #define KVM_REQ_PENDING_TIMER 5 |
| 37 | #define KVM_REQ_UNHALT 6 | 37 | #define KVM_REQ_UNHALT 6 |
| 38 | #define KVM_REQ_MMU_SYNC 7 | ||
| 38 | 39 | ||
| 39 | struct kvm_vcpu; | 40 | struct kvm_vcpu; |
| 40 | extern struct kmem_cache *kvm_vcpu_cache; | 41 | extern struct kmem_cache *kvm_vcpu_cache; |
