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