aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakuya Yoshikawa <yoshikawa_takuya_b1@lab.ntt.co.jp>2015-11-20 03:45:44 -0500
committerPaolo Bonzini <pbonzini@redhat.com>2015-11-25 11:26:47 -0500
commit77fbbbd2f09fae486190bb2bd7142647dc2a6e8b (patch)
tree540f568e2226e1cfe370c3ed7cf0bd4544b03c22
parentafd28fe1c901429eba8957f54bdb4a13cc15ae44 (diff)
KVM: x86: MMU: Consolidate BUG_ON checks for reverse-mapped sptes
At some call sites of rmap_get_first() and rmap_get_next(), BUG_ON is placed right after the call to detect unrelated sptes which must not be found in the reverse-mapping list. Move this check in rmap_get_first/next() so that all call sites, not just the users of the for_each_rmap_spte() macro, will be checked the same way. One thing to keep in mind is that kvm_mmu_unlink_parents() also uses rmap_get_first() to handle parent sptes. The change will not break it because parent sptes are present, at least until drop_parent_pte() actually unlinks them, and not mmio-sptes. Signed-off-by: Takuya Yoshikawa <yoshikawa_takuya_b1@lab.ntt.co.jp> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--Documentation/virtual/kvm/mmu.txt4
-rw-r--r--arch/x86/kvm/mmu.c26
2 files changed, 19 insertions, 11 deletions
diff --git a/Documentation/virtual/kvm/mmu.txt b/Documentation/virtual/kvm/mmu.txt
index 3a4d681c3e98..daf9c0f742d2 100644
--- a/Documentation/virtual/kvm/mmu.txt
+++ b/Documentation/virtual/kvm/mmu.txt
@@ -203,10 +203,10 @@ Shadow pages contain the following information:
203 page cannot be destroyed. See role.invalid. 203 page cannot be destroyed. See role.invalid.
204 parent_ptes: 204 parent_ptes:
205 The reverse mapping for the pte/ptes pointing at this page's spt. If 205 The reverse mapping for the pte/ptes pointing at this page's spt. If
206 parent_ptes bit 0 is zero, only one spte points at this pages and 206 parent_ptes bit 0 is zero, only one spte points at this page and
207 parent_ptes points at this single spte, otherwise, there exists multiple 207 parent_ptes points at this single spte, otherwise, there exists multiple
208 sptes pointing at this page and (parent_ptes & ~0x1) points at a data 208 sptes pointing at this page and (parent_ptes & ~0x1) points at a data
209 structure with a list of parent_ptes. 209 structure with a list of parent sptes.
210 unsync: 210 unsync:
211 If true, then the translations in this page may not match the guest's 211 If true, then the translations in this page may not match the guest's
212 translation. This is equivalent to the state of the tlb when a pte is 212 translation. This is equivalent to the state of the tlb when a pte is
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 3104748eeb48..5b249d4f4da1 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -1098,17 +1098,23 @@ struct rmap_iterator {
1098static u64 *rmap_get_first(struct kvm_rmap_head *rmap_head, 1098static u64 *rmap_get_first(struct kvm_rmap_head *rmap_head,
1099 struct rmap_iterator *iter) 1099 struct rmap_iterator *iter)
1100{ 1100{
1101 u64 *sptep;
1102
1101 if (!rmap_head->val) 1103 if (!rmap_head->val)
1102 return NULL; 1104 return NULL;
1103 1105
1104 if (!(rmap_head->val & 1)) { 1106 if (!(rmap_head->val & 1)) {
1105 iter->desc = NULL; 1107 iter->desc = NULL;
1106 return (u64 *)rmap_head->val; 1108 sptep = (u64 *)rmap_head->val;
1109 goto out;
1107 } 1110 }
1108 1111
1109 iter->desc = (struct pte_list_desc *)(rmap_head->val & ~1ul); 1112 iter->desc = (struct pte_list_desc *)(rmap_head->val & ~1ul);
1110 iter->pos = 0; 1113 iter->pos = 0;
1111 return iter->desc->sptes[iter->pos]; 1114 sptep = iter->desc->sptes[iter->pos];
1115out:
1116 BUG_ON(!is_shadow_present_pte(*sptep));
1117 return sptep;
1112} 1118}
1113 1119
1114/* 1120/*
@@ -1118,14 +1124,14 @@ static u64 *rmap_get_first(struct kvm_rmap_head *rmap_head,
1118 */ 1124 */
1119static u64 *rmap_get_next(struct rmap_iterator *iter) 1125static u64 *rmap_get_next(struct rmap_iterator *iter)
1120{ 1126{
1127 u64 *sptep;
1128
1121 if (iter->desc) { 1129 if (iter->desc) {
1122 if (iter->pos < PTE_LIST_EXT - 1) { 1130 if (iter->pos < PTE_LIST_EXT - 1) {
1123 u64 *sptep;
1124
1125 ++iter->pos; 1131 ++iter->pos;
1126 sptep = iter->desc->sptes[iter->pos]; 1132 sptep = iter->desc->sptes[iter->pos];
1127 if (sptep) 1133 if (sptep)
1128 return sptep; 1134 goto out;
1129 } 1135 }
1130 1136
1131 iter->desc = iter->desc->more; 1137 iter->desc = iter->desc->more;
@@ -1133,17 +1139,20 @@ static u64 *rmap_get_next(struct rmap_iterator *iter)
1133 if (iter->desc) { 1139 if (iter->desc) {
1134 iter->pos = 0; 1140 iter->pos = 0;
1135 /* desc->sptes[0] cannot be NULL */ 1141 /* desc->sptes[0] cannot be NULL */
1136 return iter->desc->sptes[iter->pos]; 1142 sptep = iter->desc->sptes[iter->pos];
1143 goto out;
1137 } 1144 }
1138 } 1145 }
1139 1146
1140 return NULL; 1147 return NULL;
1148out:
1149 BUG_ON(!is_shadow_present_pte(*sptep));
1150 return sptep;
1141} 1151}
1142 1152
1143#define for_each_rmap_spte(_rmap_head_, _iter_, _spte_) \ 1153#define for_each_rmap_spte(_rmap_head_, _iter_, _spte_) \
1144 for (_spte_ = rmap_get_first(_rmap_head_, _iter_); \ 1154 for (_spte_ = rmap_get_first(_rmap_head_, _iter_); \
1145 _spte_ && ({BUG_ON(!is_shadow_present_pte(*_spte_)); 1;}); \ 1155 _spte_; _spte_ = rmap_get_next(_iter_))
1146 _spte_ = rmap_get_next(_iter_))
1147 1156
1148static void drop_spte(struct kvm *kvm, u64 *sptep) 1157static void drop_spte(struct kvm *kvm, u64 *sptep)
1149{ 1158{
@@ -1358,7 +1367,6 @@ static bool kvm_zap_rmapp(struct kvm *kvm, struct kvm_rmap_head *rmap_head)
1358 bool flush = false; 1367 bool flush = false;
1359 1368
1360 while ((sptep = rmap_get_first(rmap_head, &iter))) { 1369 while ((sptep = rmap_get_first(rmap_head, &iter))) {
1361 BUG_ON(!(*sptep & PT_PRESENT_MASK));
1362 rmap_printk("%s: spte %p %llx.\n", __func__, sptep, *sptep); 1370 rmap_printk("%s: spte %p %llx.\n", __func__, sptep, *sptep);
1363 1371
1364 drop_spte(kvm, sptep); 1372 drop_spte(kvm, sptep);