diff options
| author | Takuya Yoshikawa <yoshikawa_takuya_b1@lab.ntt.co.jp> | 2015-11-20 03:45:44 -0500 |
|---|---|---|
| committer | Paolo Bonzini <pbonzini@redhat.com> | 2015-11-25 11:26:47 -0500 |
| commit | 77fbbbd2f09fae486190bb2bd7142647dc2a6e8b (patch) | |
| tree | 540f568e2226e1cfe370c3ed7cf0bd4544b03c22 | |
| parent | afd28fe1c901429eba8957f54bdb4a13cc15ae44 (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.txt | 4 | ||||
| -rw-r--r-- | arch/x86/kvm/mmu.c | 26 |
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 { | |||
| 1098 | static u64 *rmap_get_first(struct kvm_rmap_head *rmap_head, | 1098 | static 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]; |
| 1115 | out: | ||
| 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 | */ |
| 1119 | static u64 *rmap_get_next(struct rmap_iterator *iter) | 1125 | static 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; |
| 1148 | out: | ||
| 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 | ||
| 1148 | static void drop_spte(struct kvm *kvm, u64 *sptep) | 1157 | static 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); |
