18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci
38c2ecf20Sopenharmony_ci#ifndef KVM_X86_MMU_SPTE_H
48c2ecf20Sopenharmony_ci#define KVM_X86_MMU_SPTE_H
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include "mmu_internal.h"
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#define PT_FIRST_AVAIL_BITS_SHIFT 10
98c2ecf20Sopenharmony_ci#define PT64_SECOND_AVAIL_BITS_SHIFT 54
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci/*
128c2ecf20Sopenharmony_ci * The mask used to denote special SPTEs, which can be either MMIO SPTEs or
138c2ecf20Sopenharmony_ci * Access Tracking SPTEs.
148c2ecf20Sopenharmony_ci */
158c2ecf20Sopenharmony_ci#define SPTE_SPECIAL_MASK (3ULL << 52)
168c2ecf20Sopenharmony_ci#define SPTE_AD_ENABLED_MASK (0ULL << 52)
178c2ecf20Sopenharmony_ci#define SPTE_AD_DISABLED_MASK (1ULL << 52)
188c2ecf20Sopenharmony_ci#define SPTE_AD_WRPROT_ONLY_MASK (2ULL << 52)
198c2ecf20Sopenharmony_ci#define SPTE_MMIO_MASK (3ULL << 52)
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#ifdef CONFIG_DYNAMIC_PHYSICAL_MASK
228c2ecf20Sopenharmony_ci#define PT64_BASE_ADDR_MASK (physical_mask & ~(u64)(PAGE_SIZE-1))
238c2ecf20Sopenharmony_ci#else
248c2ecf20Sopenharmony_ci#define PT64_BASE_ADDR_MASK (((1ULL << 52) - 1) & ~(u64)(PAGE_SIZE-1))
258c2ecf20Sopenharmony_ci#endif
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci#define PT64_PERM_MASK (PT_PRESENT_MASK | PT_WRITABLE_MASK | shadow_user_mask \
288c2ecf20Sopenharmony_ci			| shadow_x_mask | shadow_nx_mask | shadow_me_mask)
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#define ACC_EXEC_MASK    1
318c2ecf20Sopenharmony_ci#define ACC_WRITE_MASK   PT_WRITABLE_MASK
328c2ecf20Sopenharmony_ci#define ACC_USER_MASK    PT_USER_MASK
338c2ecf20Sopenharmony_ci#define ACC_ALL          (ACC_EXEC_MASK | ACC_WRITE_MASK | ACC_USER_MASK)
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci/* The mask for the R/X bits in EPT PTEs */
368c2ecf20Sopenharmony_ci#define PT64_EPT_READABLE_MASK			0x1ull
378c2ecf20Sopenharmony_ci#define PT64_EPT_EXECUTABLE_MASK		0x4ull
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci#define PT64_LEVEL_BITS 9
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#define PT64_LEVEL_SHIFT(level) \
428c2ecf20Sopenharmony_ci		(PAGE_SHIFT + (level - 1) * PT64_LEVEL_BITS)
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci#define PT64_INDEX(address, level)\
458c2ecf20Sopenharmony_ci	(((address) >> PT64_LEVEL_SHIFT(level)) & ((1 << PT64_LEVEL_BITS) - 1))
468c2ecf20Sopenharmony_ci#define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level)
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci#define SPTE_HOST_WRITEABLE	(1ULL << PT_FIRST_AVAIL_BITS_SHIFT)
508c2ecf20Sopenharmony_ci#define SPTE_MMU_WRITEABLE	(1ULL << (PT_FIRST_AVAIL_BITS_SHIFT + 1))
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci/*
538c2ecf20Sopenharmony_ci * Due to limited space in PTEs, the MMIO generation is a 18 bit subset of
548c2ecf20Sopenharmony_ci * the memslots generation and is derived as follows:
558c2ecf20Sopenharmony_ci *
568c2ecf20Sopenharmony_ci * Bits 0-8 of the MMIO generation are propagated to spte bits 3-11
578c2ecf20Sopenharmony_ci * Bits 9-17 of the MMIO generation are propagated to spte bits 54-62
588c2ecf20Sopenharmony_ci *
598c2ecf20Sopenharmony_ci * The KVM_MEMSLOT_GEN_UPDATE_IN_PROGRESS flag is intentionally not included in
608c2ecf20Sopenharmony_ci * the MMIO generation number, as doing so would require stealing a bit from
618c2ecf20Sopenharmony_ci * the "real" generation number and thus effectively halve the maximum number
628c2ecf20Sopenharmony_ci * of MMIO generations that can be handled before encountering a wrap (which
638c2ecf20Sopenharmony_ci * requires a full MMU zap).  The flag is instead explicitly queried when
648c2ecf20Sopenharmony_ci * checking for MMIO spte cache hits.
658c2ecf20Sopenharmony_ci */
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci#define MMIO_SPTE_GEN_LOW_START		3
688c2ecf20Sopenharmony_ci#define MMIO_SPTE_GEN_LOW_END		11
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci#define MMIO_SPTE_GEN_HIGH_START	PT64_SECOND_AVAIL_BITS_SHIFT
718c2ecf20Sopenharmony_ci#define MMIO_SPTE_GEN_HIGH_END		62
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci#define MMIO_SPTE_GEN_LOW_MASK		GENMASK_ULL(MMIO_SPTE_GEN_LOW_END, \
748c2ecf20Sopenharmony_ci						    MMIO_SPTE_GEN_LOW_START)
758c2ecf20Sopenharmony_ci#define MMIO_SPTE_GEN_HIGH_MASK		GENMASK_ULL(MMIO_SPTE_GEN_HIGH_END, \
768c2ecf20Sopenharmony_ci						    MMIO_SPTE_GEN_HIGH_START)
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci#define MMIO_SPTE_GEN_LOW_BITS		(MMIO_SPTE_GEN_LOW_END - MMIO_SPTE_GEN_LOW_START + 1)
798c2ecf20Sopenharmony_ci#define MMIO_SPTE_GEN_HIGH_BITS		(MMIO_SPTE_GEN_HIGH_END - MMIO_SPTE_GEN_HIGH_START + 1)
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci/* remember to adjust the comment above as well if you change these */
828c2ecf20Sopenharmony_cistatic_assert(MMIO_SPTE_GEN_LOW_BITS == 9 && MMIO_SPTE_GEN_HIGH_BITS == 9);
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci#define MMIO_SPTE_GEN_LOW_SHIFT		(MMIO_SPTE_GEN_LOW_START - 0)
858c2ecf20Sopenharmony_ci#define MMIO_SPTE_GEN_HIGH_SHIFT	(MMIO_SPTE_GEN_HIGH_START - MMIO_SPTE_GEN_LOW_BITS)
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci#define MMIO_SPTE_GEN_MASK		GENMASK_ULL(MMIO_SPTE_GEN_LOW_BITS + MMIO_SPTE_GEN_HIGH_BITS - 1, 0)
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ciextern u64 __read_mostly shadow_nx_mask;
908c2ecf20Sopenharmony_ciextern u64 __read_mostly shadow_x_mask; /* mutual exclusive with nx_mask */
918c2ecf20Sopenharmony_ciextern u64 __read_mostly shadow_user_mask;
928c2ecf20Sopenharmony_ciextern u64 __read_mostly shadow_accessed_mask;
938c2ecf20Sopenharmony_ciextern u64 __read_mostly shadow_dirty_mask;
948c2ecf20Sopenharmony_ciextern u64 __read_mostly shadow_mmio_value;
958c2ecf20Sopenharmony_ciextern u64 __read_mostly shadow_mmio_access_mask;
968c2ecf20Sopenharmony_ciextern u64 __read_mostly shadow_present_mask;
978c2ecf20Sopenharmony_ciextern u64 __read_mostly shadow_me_mask;
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci/*
1008c2ecf20Sopenharmony_ci * SPTEs used by MMUs without A/D bits are marked with SPTE_AD_DISABLED_MASK;
1018c2ecf20Sopenharmony_ci * shadow_acc_track_mask is the set of bits to be cleared in non-accessed
1028c2ecf20Sopenharmony_ci * pages.
1038c2ecf20Sopenharmony_ci */
1048c2ecf20Sopenharmony_ciextern u64 __read_mostly shadow_acc_track_mask;
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci/*
1078c2ecf20Sopenharmony_ci * This mask must be set on all non-zero Non-Present or Reserved SPTEs in order
1088c2ecf20Sopenharmony_ci * to guard against L1TF attacks.
1098c2ecf20Sopenharmony_ci */
1108c2ecf20Sopenharmony_ciextern u64 __read_mostly shadow_nonpresent_or_rsvd_mask;
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci/*
1138c2ecf20Sopenharmony_ci * The number of high-order 1 bits to use in the mask above.
1148c2ecf20Sopenharmony_ci */
1158c2ecf20Sopenharmony_ci#define SHADOW_NONPRESENT_OR_RSVD_MASK_LEN 5
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci/*
1188c2ecf20Sopenharmony_ci * The mask/shift to use for saving the original R/X bits when marking the PTE
1198c2ecf20Sopenharmony_ci * as not-present for access tracking purposes. We do not save the W bit as the
1208c2ecf20Sopenharmony_ci * PTEs being access tracked also need to be dirty tracked, so the W bit will be
1218c2ecf20Sopenharmony_ci * restored only when a write is attempted to the page.
1228c2ecf20Sopenharmony_ci */
1238c2ecf20Sopenharmony_ci#define SHADOW_ACC_TRACK_SAVED_BITS_MASK (PT64_EPT_READABLE_MASK | \
1248c2ecf20Sopenharmony_ci					  PT64_EPT_EXECUTABLE_MASK)
1258c2ecf20Sopenharmony_ci#define SHADOW_ACC_TRACK_SAVED_BITS_SHIFT PT64_SECOND_AVAIL_BITS_SHIFT
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci/*
1288c2ecf20Sopenharmony_ci * In some cases, we need to preserve the GFN of a non-present or reserved
1298c2ecf20Sopenharmony_ci * SPTE when we usurp the upper five bits of the physical address space to
1308c2ecf20Sopenharmony_ci * defend against L1TF, e.g. for MMIO SPTEs.  To preserve the GFN, we'll
1318c2ecf20Sopenharmony_ci * shift bits of the GFN that overlap with shadow_nonpresent_or_rsvd_mask
1328c2ecf20Sopenharmony_ci * left into the reserved bits, i.e. the GFN in the SPTE will be split into
1338c2ecf20Sopenharmony_ci * high and low parts.  This mask covers the lower bits of the GFN.
1348c2ecf20Sopenharmony_ci */
1358c2ecf20Sopenharmony_ciextern u64 __read_mostly shadow_nonpresent_or_rsvd_lower_gfn_mask;
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci/*
1388c2ecf20Sopenharmony_ci * The number of non-reserved physical address bits irrespective of features
1398c2ecf20Sopenharmony_ci * that repurpose legal bits, e.g. MKTME.
1408c2ecf20Sopenharmony_ci */
1418c2ecf20Sopenharmony_ciextern u8 __read_mostly shadow_phys_bits;
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_cistatic inline bool is_mmio_spte(u64 spte)
1448c2ecf20Sopenharmony_ci{
1458c2ecf20Sopenharmony_ci	return (spte & SPTE_SPECIAL_MASK) == SPTE_MMIO_MASK;
1468c2ecf20Sopenharmony_ci}
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_cistatic inline bool sp_ad_disabled(struct kvm_mmu_page *sp)
1498c2ecf20Sopenharmony_ci{
1508c2ecf20Sopenharmony_ci	return sp->role.ad_disabled;
1518c2ecf20Sopenharmony_ci}
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_cistatic inline bool spte_ad_enabled(u64 spte)
1548c2ecf20Sopenharmony_ci{
1558c2ecf20Sopenharmony_ci	MMU_WARN_ON(is_mmio_spte(spte));
1568c2ecf20Sopenharmony_ci	return (spte & SPTE_SPECIAL_MASK) != SPTE_AD_DISABLED_MASK;
1578c2ecf20Sopenharmony_ci}
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_cistatic inline bool spte_ad_need_write_protect(u64 spte)
1608c2ecf20Sopenharmony_ci{
1618c2ecf20Sopenharmony_ci	MMU_WARN_ON(is_mmio_spte(spte));
1628c2ecf20Sopenharmony_ci	return (spte & SPTE_SPECIAL_MASK) != SPTE_AD_ENABLED_MASK;
1638c2ecf20Sopenharmony_ci}
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_cistatic inline u64 spte_shadow_accessed_mask(u64 spte)
1668c2ecf20Sopenharmony_ci{
1678c2ecf20Sopenharmony_ci	MMU_WARN_ON(is_mmio_spte(spte));
1688c2ecf20Sopenharmony_ci	return spte_ad_enabled(spte) ? shadow_accessed_mask : 0;
1698c2ecf20Sopenharmony_ci}
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_cistatic inline u64 spte_shadow_dirty_mask(u64 spte)
1728c2ecf20Sopenharmony_ci{
1738c2ecf20Sopenharmony_ci	MMU_WARN_ON(is_mmio_spte(spte));
1748c2ecf20Sopenharmony_ci	return spte_ad_enabled(spte) ? shadow_dirty_mask : 0;
1758c2ecf20Sopenharmony_ci}
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_cistatic inline bool is_access_track_spte(u64 spte)
1788c2ecf20Sopenharmony_ci{
1798c2ecf20Sopenharmony_ci	return !spte_ad_enabled(spte) && (spte & shadow_acc_track_mask) == 0;
1808c2ecf20Sopenharmony_ci}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_cistatic inline int is_shadow_present_pte(u64 pte)
1838c2ecf20Sopenharmony_ci{
1848c2ecf20Sopenharmony_ci	return (pte != 0) && !is_mmio_spte(pte);
1858c2ecf20Sopenharmony_ci}
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_cistatic inline int is_large_pte(u64 pte)
1888c2ecf20Sopenharmony_ci{
1898c2ecf20Sopenharmony_ci	return pte & PT_PAGE_SIZE_MASK;
1908c2ecf20Sopenharmony_ci}
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_cistatic inline int is_last_spte(u64 pte, int level)
1938c2ecf20Sopenharmony_ci{
1948c2ecf20Sopenharmony_ci	if (level == PG_LEVEL_4K)
1958c2ecf20Sopenharmony_ci		return 1;
1968c2ecf20Sopenharmony_ci	if (is_large_pte(pte))
1978c2ecf20Sopenharmony_ci		return 1;
1988c2ecf20Sopenharmony_ci	return 0;
1998c2ecf20Sopenharmony_ci}
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_cistatic inline bool is_executable_pte(u64 spte)
2028c2ecf20Sopenharmony_ci{
2038c2ecf20Sopenharmony_ci	return (spte & (shadow_x_mask | shadow_nx_mask)) == shadow_x_mask;
2048c2ecf20Sopenharmony_ci}
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_cistatic inline kvm_pfn_t spte_to_pfn(u64 pte)
2078c2ecf20Sopenharmony_ci{
2088c2ecf20Sopenharmony_ci	return (pte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT;
2098c2ecf20Sopenharmony_ci}
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_cistatic inline bool is_accessed_spte(u64 spte)
2128c2ecf20Sopenharmony_ci{
2138c2ecf20Sopenharmony_ci	u64 accessed_mask = spte_shadow_accessed_mask(spte);
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	return accessed_mask ? spte & accessed_mask
2168c2ecf20Sopenharmony_ci			     : !is_access_track_spte(spte);
2178c2ecf20Sopenharmony_ci}
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_cistatic inline bool is_dirty_spte(u64 spte)
2208c2ecf20Sopenharmony_ci{
2218c2ecf20Sopenharmony_ci	u64 dirty_mask = spte_shadow_dirty_mask(spte);
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	return dirty_mask ? spte & dirty_mask : spte & PT_WRITABLE_MASK;
2248c2ecf20Sopenharmony_ci}
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_cistatic inline bool spte_can_locklessly_be_made_writable(u64 spte)
2278c2ecf20Sopenharmony_ci{
2288c2ecf20Sopenharmony_ci	return (spte & (SPTE_HOST_WRITEABLE | SPTE_MMU_WRITEABLE)) ==
2298c2ecf20Sopenharmony_ci		(SPTE_HOST_WRITEABLE | SPTE_MMU_WRITEABLE);
2308c2ecf20Sopenharmony_ci}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_cistatic inline u64 get_mmio_spte_generation(u64 spte)
2338c2ecf20Sopenharmony_ci{
2348c2ecf20Sopenharmony_ci	u64 gen;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	gen = (spte & MMIO_SPTE_GEN_LOW_MASK) >> MMIO_SPTE_GEN_LOW_SHIFT;
2378c2ecf20Sopenharmony_ci	gen |= (spte & MMIO_SPTE_GEN_HIGH_MASK) >> MMIO_SPTE_GEN_HIGH_SHIFT;
2388c2ecf20Sopenharmony_ci	return gen;
2398c2ecf20Sopenharmony_ci}
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci/* Bits which may be returned by set_spte() */
2428c2ecf20Sopenharmony_ci#define SET_SPTE_WRITE_PROTECTED_PT    BIT(0)
2438c2ecf20Sopenharmony_ci#define SET_SPTE_NEED_REMOTE_TLB_FLUSH BIT(1)
2448c2ecf20Sopenharmony_ci#define SET_SPTE_SPURIOUS              BIT(2)
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ciint make_spte(struct kvm_vcpu *vcpu, unsigned int pte_access, int level,
2478c2ecf20Sopenharmony_ci		     gfn_t gfn, kvm_pfn_t pfn, u64 old_spte, bool speculative,
2488c2ecf20Sopenharmony_ci		     bool can_unsync, bool host_writable, bool ad_disabled,
2498c2ecf20Sopenharmony_ci		     u64 *new_spte);
2508c2ecf20Sopenharmony_ciu64 make_nonleaf_spte(u64 *child_pt, bool ad_disabled);
2518c2ecf20Sopenharmony_ciu64 make_mmio_spte(struct kvm_vcpu *vcpu, u64 gfn, unsigned int access);
2528c2ecf20Sopenharmony_ciu64 mark_spte_for_access_track(u64 spte);
2538c2ecf20Sopenharmony_ciu64 kvm_mmu_changed_pte_notifier_make_spte(u64 old_spte, kvm_pfn_t new_pfn);
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_civoid kvm_mmu_reset_all_pte_masks(void);
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci#endif
258