0001
0002
0003 #include "mmu_internal.h"
0004 #include "tdp_iter.h"
0005 #include "spte.h"
0006
0007
0008
0009
0010
0011 static void tdp_iter_refresh_sptep(struct tdp_iter *iter)
0012 {
0013 iter->sptep = iter->pt_path[iter->level - 1] +
0014 SPTE_INDEX(iter->gfn << PAGE_SHIFT, iter->level);
0015 iter->old_spte = kvm_tdp_mmu_read_spte(iter->sptep);
0016 }
0017
0018 static gfn_t round_gfn_for_level(gfn_t gfn, int level)
0019 {
0020 return gfn & -KVM_PAGES_PER_HPAGE(level);
0021 }
0022
0023
0024
0025
0026
0027 void tdp_iter_restart(struct tdp_iter *iter)
0028 {
0029 iter->yielded = false;
0030 iter->yielded_gfn = iter->next_last_level_gfn;
0031 iter->level = iter->root_level;
0032
0033 iter->gfn = round_gfn_for_level(iter->next_last_level_gfn, iter->level);
0034 tdp_iter_refresh_sptep(iter);
0035
0036 iter->valid = true;
0037 }
0038
0039
0040
0041
0042
0043 void tdp_iter_start(struct tdp_iter *iter, struct kvm_mmu_page *root,
0044 int min_level, gfn_t next_last_level_gfn)
0045 {
0046 int root_level = root->role.level;
0047
0048 WARN_ON(root_level < 1);
0049 WARN_ON(root_level > PT64_ROOT_MAX_LEVEL);
0050
0051 iter->next_last_level_gfn = next_last_level_gfn;
0052 iter->root_level = root_level;
0053 iter->min_level = min_level;
0054 iter->pt_path[iter->root_level - 1] = (tdp_ptep_t)root->spt;
0055 iter->as_id = kvm_mmu_page_as_id(root);
0056
0057 tdp_iter_restart(iter);
0058 }
0059
0060
0061
0062
0063
0064
0065 tdp_ptep_t spte_to_child_pt(u64 spte, int level)
0066 {
0067
0068
0069
0070
0071 if (!is_shadow_present_pte(spte) || is_last_spte(spte, level))
0072 return NULL;
0073
0074 return (tdp_ptep_t)__va(spte_to_pfn(spte) << PAGE_SHIFT);
0075 }
0076
0077
0078
0079
0080
0081 static bool try_step_down(struct tdp_iter *iter)
0082 {
0083 tdp_ptep_t child_pt;
0084
0085 if (iter->level == iter->min_level)
0086 return false;
0087
0088
0089
0090
0091
0092 iter->old_spte = kvm_tdp_mmu_read_spte(iter->sptep);
0093
0094 child_pt = spte_to_child_pt(iter->old_spte, iter->level);
0095 if (!child_pt)
0096 return false;
0097
0098 iter->level--;
0099 iter->pt_path[iter->level - 1] = child_pt;
0100 iter->gfn = round_gfn_for_level(iter->next_last_level_gfn, iter->level);
0101 tdp_iter_refresh_sptep(iter);
0102
0103 return true;
0104 }
0105
0106
0107
0108
0109
0110
0111
0112
0113 static bool try_step_side(struct tdp_iter *iter)
0114 {
0115
0116
0117
0118
0119 if (SPTE_INDEX(iter->gfn << PAGE_SHIFT, iter->level) ==
0120 (SPTE_ENT_PER_PAGE - 1))
0121 return false;
0122
0123 iter->gfn += KVM_PAGES_PER_HPAGE(iter->level);
0124 iter->next_last_level_gfn = iter->gfn;
0125 iter->sptep++;
0126 iter->old_spte = kvm_tdp_mmu_read_spte(iter->sptep);
0127
0128 return true;
0129 }
0130
0131
0132
0133
0134
0135
0136 static bool try_step_up(struct tdp_iter *iter)
0137 {
0138 if (iter->level == iter->root_level)
0139 return false;
0140
0141 iter->level++;
0142 iter->gfn = round_gfn_for_level(iter->gfn, iter->level);
0143 tdp_iter_refresh_sptep(iter);
0144
0145 return true;
0146 }
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164 void tdp_iter_next(struct tdp_iter *iter)
0165 {
0166 if (iter->yielded) {
0167 tdp_iter_restart(iter);
0168 return;
0169 }
0170
0171 if (try_step_down(iter))
0172 return;
0173
0174 do {
0175 if (try_step_side(iter))
0176 return;
0177 } while (try_step_up(iter));
0178 iter->valid = false;
0179 }
0180