18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci#ifndef __KVM_X86_MMU_TDP_ITER_H 48c2ecf20Sopenharmony_ci#define __KVM_X86_MMU_TDP_ITER_H 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/kvm_host.h> 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include "mmu.h" 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci/* 118c2ecf20Sopenharmony_ci * A TDP iterator performs a pre-order walk over a TDP paging structure. 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_cistruct tdp_iter { 148c2ecf20Sopenharmony_ci /* 158c2ecf20Sopenharmony_ci * The iterator will traverse the paging structure towards the mapping 168c2ecf20Sopenharmony_ci * for this GFN. 178c2ecf20Sopenharmony_ci */ 188c2ecf20Sopenharmony_ci gfn_t next_last_level_gfn; 198c2ecf20Sopenharmony_ci /* 208c2ecf20Sopenharmony_ci * The next_last_level_gfn at the time when the thread last 218c2ecf20Sopenharmony_ci * yielded. Only yielding when the next_last_level_gfn != 228c2ecf20Sopenharmony_ci * yielded_gfn helps ensure forward progress. 238c2ecf20Sopenharmony_ci */ 248c2ecf20Sopenharmony_ci gfn_t yielded_gfn; 258c2ecf20Sopenharmony_ci /* Pointers to the page tables traversed to reach the current SPTE */ 268c2ecf20Sopenharmony_ci u64 *pt_path[PT64_ROOT_MAX_LEVEL]; 278c2ecf20Sopenharmony_ci /* A pointer to the current SPTE */ 288c2ecf20Sopenharmony_ci u64 *sptep; 298c2ecf20Sopenharmony_ci /* The lowest GFN mapped by the current SPTE */ 308c2ecf20Sopenharmony_ci gfn_t gfn; 318c2ecf20Sopenharmony_ci /* The level of the root page given to the iterator */ 328c2ecf20Sopenharmony_ci int root_level; 338c2ecf20Sopenharmony_ci /* The lowest level the iterator should traverse to */ 348c2ecf20Sopenharmony_ci int min_level; 358c2ecf20Sopenharmony_ci /* The iterator's current level within the paging structure */ 368c2ecf20Sopenharmony_ci int level; 378c2ecf20Sopenharmony_ci /* A snapshot of the value at sptep */ 388c2ecf20Sopenharmony_ci u64 old_spte; 398c2ecf20Sopenharmony_ci /* 408c2ecf20Sopenharmony_ci * Whether the iterator has a valid state. This will be false if the 418c2ecf20Sopenharmony_ci * iterator walks off the end of the paging structure. 428c2ecf20Sopenharmony_ci */ 438c2ecf20Sopenharmony_ci bool valid; 448c2ecf20Sopenharmony_ci}; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci/* 478c2ecf20Sopenharmony_ci * Iterates over every SPTE mapping the GFN range [start, end) in a 488c2ecf20Sopenharmony_ci * preorder traversal. 498c2ecf20Sopenharmony_ci */ 508c2ecf20Sopenharmony_ci#define for_each_tdp_pte_min_level(iter, root, root_level, min_level, start, end) \ 518c2ecf20Sopenharmony_ci for (tdp_iter_start(&iter, root, root_level, min_level, start); \ 528c2ecf20Sopenharmony_ci iter.valid && iter.gfn < end; \ 538c2ecf20Sopenharmony_ci tdp_iter_next(&iter)) 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci#define for_each_tdp_pte(iter, root, root_level, start, end) \ 568c2ecf20Sopenharmony_ci for_each_tdp_pte_min_level(iter, root, root_level, PG_LEVEL_4K, start, end) 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ciu64 *spte_to_child_pt(u64 pte, int level); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_civoid tdp_iter_start(struct tdp_iter *iter, u64 *root_pt, int root_level, 618c2ecf20Sopenharmony_ci int min_level, gfn_t next_last_level_gfn); 628c2ecf20Sopenharmony_civoid tdp_iter_next(struct tdp_iter *iter); 638c2ecf20Sopenharmony_ciu64 *tdp_iter_root_pt(struct tdp_iter *iter); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci#endif /* __KVM_X86_MMU_TDP_ITER_H */ 66