18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef __KVM_X86_MMU_INTERNAL_H 38c2ecf20Sopenharmony_ci#define __KVM_X86_MMU_INTERNAL_H 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#include <linux/types.h> 68c2ecf20Sopenharmony_ci#include <linux/kvm_host.h> 78c2ecf20Sopenharmony_ci#include <asm/kvm_host.h> 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#undef MMU_DEBUG 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#ifdef MMU_DEBUG 128c2ecf20Sopenharmony_ciextern bool dbg; 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#define pgprintk(x...) do { if (dbg) printk(x); } while (0) 158c2ecf20Sopenharmony_ci#define rmap_printk(x...) do { if (dbg) printk(x); } while (0) 168c2ecf20Sopenharmony_ci#define MMU_WARN_ON(x) WARN_ON(x) 178c2ecf20Sopenharmony_ci#else 188c2ecf20Sopenharmony_ci#define pgprintk(x...) do { } while (0) 198c2ecf20Sopenharmony_ci#define rmap_printk(x...) do { } while (0) 208c2ecf20Sopenharmony_ci#define MMU_WARN_ON(x) do { } while (0) 218c2ecf20Sopenharmony_ci#endif 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistruct kvm_mmu_page { 248c2ecf20Sopenharmony_ci struct list_head link; 258c2ecf20Sopenharmony_ci struct hlist_node hash_link; 268c2ecf20Sopenharmony_ci struct list_head lpage_disallowed_link; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci bool unsync; 298c2ecf20Sopenharmony_ci u8 mmu_valid_gen; 308c2ecf20Sopenharmony_ci bool mmio_cached; 318c2ecf20Sopenharmony_ci bool lpage_disallowed; /* Can't be replaced by an equiv large page */ 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci /* 348c2ecf20Sopenharmony_ci * The following two entries are used to key the shadow page in the 358c2ecf20Sopenharmony_ci * hash table. 368c2ecf20Sopenharmony_ci */ 378c2ecf20Sopenharmony_ci union kvm_mmu_page_role role; 388c2ecf20Sopenharmony_ci gfn_t gfn; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci u64 *spt; 418c2ecf20Sopenharmony_ci /* hold the gfn of each spte inside spt */ 428c2ecf20Sopenharmony_ci gfn_t *gfns; 438c2ecf20Sopenharmony_ci int root_count; /* Currently serving as active root */ 448c2ecf20Sopenharmony_ci unsigned int unsync_children; 458c2ecf20Sopenharmony_ci struct kvm_rmap_head parent_ptes; /* rmap pointers to parent sptes */ 468c2ecf20Sopenharmony_ci DECLARE_BITMAP(unsync_child_bitmap, 512); 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_32 498c2ecf20Sopenharmony_ci /* 508c2ecf20Sopenharmony_ci * Used out of the mmu-lock to avoid reading spte values while an 518c2ecf20Sopenharmony_ci * update is in progress; see the comments in __get_spte_lockless(). 528c2ecf20Sopenharmony_ci */ 538c2ecf20Sopenharmony_ci int clear_spte_count; 548c2ecf20Sopenharmony_ci#endif 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci /* Number of writes since the last time traversal visited this page. */ 578c2ecf20Sopenharmony_ci atomic_t write_flooding_count; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci bool tdp_mmu_page; 608c2ecf20Sopenharmony_ci}; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ciextern struct kmem_cache *mmu_page_header_cache; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic inline struct kvm_mmu_page *to_shadow_page(hpa_t shadow_page) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci struct page *page = pfn_to_page(shadow_page >> PAGE_SHIFT); 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci return (struct kvm_mmu_page *)page_private(page); 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_cistatic inline struct kvm_mmu_page *sptep_to_sp(u64 *sptep) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci return to_shadow_page(__pa(sptep)); 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistatic inline bool kvm_vcpu_ad_need_write_protect(struct kvm_vcpu *vcpu) 778c2ecf20Sopenharmony_ci{ 788c2ecf20Sopenharmony_ci /* 798c2ecf20Sopenharmony_ci * When using the EPT page-modification log, the GPAs in the log 808c2ecf20Sopenharmony_ci * would come from L2 rather than L1. Therefore, we need to rely 818c2ecf20Sopenharmony_ci * on write protection to record dirty pages. This also bypasses 828c2ecf20Sopenharmony_ci * PML, since writes now result in a vmexit. 838c2ecf20Sopenharmony_ci */ 848c2ecf20Sopenharmony_ci return vcpu->arch.mmu == &vcpu->arch.guest_mmu; 858c2ecf20Sopenharmony_ci} 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_cibool is_nx_huge_page_enabled(void); 888c2ecf20Sopenharmony_cibool mmu_need_write_protect(struct kvm_vcpu *vcpu, gfn_t gfn, 898c2ecf20Sopenharmony_ci bool can_unsync); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_civoid kvm_mmu_gfn_disallow_lpage(struct kvm_memory_slot *slot, gfn_t gfn); 928c2ecf20Sopenharmony_civoid kvm_mmu_gfn_allow_lpage(struct kvm_memory_slot *slot, gfn_t gfn); 938c2ecf20Sopenharmony_cibool kvm_mmu_slot_gfn_write_protect(struct kvm *kvm, 948c2ecf20Sopenharmony_ci struct kvm_memory_slot *slot, u64 gfn); 958c2ecf20Sopenharmony_civoid kvm_flush_remote_tlbs_with_address(struct kvm *kvm, 968c2ecf20Sopenharmony_ci u64 start_gfn, u64 pages); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_cistatic inline void kvm_mmu_get_root(struct kvm *kvm, struct kvm_mmu_page *sp) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci BUG_ON(!sp->root_count); 1018c2ecf20Sopenharmony_ci lockdep_assert_held(&kvm->mmu_lock); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci ++sp->root_count; 1048c2ecf20Sopenharmony_ci} 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_cistatic inline bool kvm_mmu_put_root(struct kvm *kvm, struct kvm_mmu_page *sp) 1078c2ecf20Sopenharmony_ci{ 1088c2ecf20Sopenharmony_ci lockdep_assert_held(&kvm->mmu_lock); 1098c2ecf20Sopenharmony_ci --sp->root_count; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci return !sp->root_count; 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci/* 1158c2ecf20Sopenharmony_ci * Return values of handle_mmio_page_fault, mmu.page_fault, and fast_page_fault(). 1168c2ecf20Sopenharmony_ci * 1178c2ecf20Sopenharmony_ci * RET_PF_RETRY: let CPU fault again on the address. 1188c2ecf20Sopenharmony_ci * RET_PF_EMULATE: mmio page fault, emulate the instruction directly. 1198c2ecf20Sopenharmony_ci * RET_PF_INVALID: the spte is invalid, let the real page fault path update it. 1208c2ecf20Sopenharmony_ci * RET_PF_FIXED: The faulting entry has been fixed. 1218c2ecf20Sopenharmony_ci * RET_PF_SPURIOUS: The faulting entry was already fixed, e.g. by another vCPU. 1228c2ecf20Sopenharmony_ci */ 1238c2ecf20Sopenharmony_cienum { 1248c2ecf20Sopenharmony_ci RET_PF_RETRY = 0, 1258c2ecf20Sopenharmony_ci RET_PF_EMULATE, 1268c2ecf20Sopenharmony_ci RET_PF_INVALID, 1278c2ecf20Sopenharmony_ci RET_PF_FIXED, 1288c2ecf20Sopenharmony_ci RET_PF_SPURIOUS, 1298c2ecf20Sopenharmony_ci}; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci/* Bits which may be returned by set_spte() */ 1328c2ecf20Sopenharmony_ci#define SET_SPTE_WRITE_PROTECTED_PT BIT(0) 1338c2ecf20Sopenharmony_ci#define SET_SPTE_NEED_REMOTE_TLB_FLUSH BIT(1) 1348c2ecf20Sopenharmony_ci#define SET_SPTE_SPURIOUS BIT(2) 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ciint kvm_mmu_hugepage_adjust(struct kvm_vcpu *vcpu, gfn_t gfn, 1378c2ecf20Sopenharmony_ci int max_level, kvm_pfn_t *pfnp, 1388c2ecf20Sopenharmony_ci bool huge_page_disallowed, int *req_level); 1398c2ecf20Sopenharmony_civoid disallowed_hugepage_adjust(u64 spte, gfn_t gfn, int cur_level, 1408c2ecf20Sopenharmony_ci kvm_pfn_t *pfnp, int *goal_levelp); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cibool is_nx_huge_page_enabled(void); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_civoid *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_civoid account_huge_nx_page(struct kvm *kvm, struct kvm_mmu_page *sp); 1478c2ecf20Sopenharmony_civoid unaccount_huge_nx_page(struct kvm *kvm, struct kvm_mmu_page *sp); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci#endif /* __KVM_X86_MMU_INTERNAL_H */ 150