Commit 1e21b538 authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

Merge branch 'kvm-vmx-ve' into HEAD

Allow a non-zero value for non-present SPTE and removed SPTE,
so that TDX can set the "suppress VE" bit.
parents 40269c03 8131cf5b
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1313,6 +1313,8 @@ struct kvm_arch {
	 */
	spinlock_t mmu_unsync_pages_lock;

	u64 shadow_mmio_value;

	struct iommu_domain *iommu_domain;
	bool iommu_noncoherent;
#define __KVM_HAVE_ARCH_NONCOHERENT_DMA
+13 −0
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@
#define SECONDARY_EXEC_ENCLS_EXITING		VMCS_CONTROL_BIT(ENCLS_EXITING)
#define SECONDARY_EXEC_RDSEED_EXITING		VMCS_CONTROL_BIT(RDSEED_EXITING)
#define SECONDARY_EXEC_ENABLE_PML               VMCS_CONTROL_BIT(PAGE_MOD_LOGGING)
#define SECONDARY_EXEC_EPT_VIOLATION_VE		VMCS_CONTROL_BIT(EPT_VIOLATION_VE)
#define SECONDARY_EXEC_PT_CONCEAL_VMX		VMCS_CONTROL_BIT(PT_CONCEAL_VMX)
#define SECONDARY_EXEC_ENABLE_XSAVES		VMCS_CONTROL_BIT(XSAVES)
#define SECONDARY_EXEC_MODE_BASED_EPT_EXEC	VMCS_CONTROL_BIT(MODE_BASED_EPT_EXEC)
@@ -226,6 +227,8 @@ enum vmcs_field {
	VMREAD_BITMAP_HIGH              = 0x00002027,
	VMWRITE_BITMAP                  = 0x00002028,
	VMWRITE_BITMAP_HIGH             = 0x00002029,
	VE_INFORMATION_ADDRESS		= 0x0000202A,
	VE_INFORMATION_ADDRESS_HIGH	= 0x0000202B,
	XSS_EXIT_BITMAP                 = 0x0000202C,
	XSS_EXIT_BITMAP_HIGH            = 0x0000202D,
	ENCLS_EXITING_BITMAP		= 0x0000202E,
@@ -514,6 +517,7 @@ enum vmcs_field {
#define VMX_EPT_IPAT_BIT    			(1ull << 6)
#define VMX_EPT_ACCESS_BIT			(1ull << 8)
#define VMX_EPT_DIRTY_BIT			(1ull << 9)
#define VMX_EPT_SUPPRESS_VE_BIT			(1ull << 63)
#define VMX_EPT_RWX_MASK                        (VMX_EPT_READABLE_MASK |       \
						 VMX_EPT_WRITABLE_MASK |       \
						 VMX_EPT_EXECUTABLE_MASK)
@@ -630,4 +634,13 @@ enum vmx_l1d_flush_state {

extern enum vmx_l1d_flush_state l1tf_vmx_mitigation;

struct vmx_ve_information {
	u32 exit_reason;
	u32 delivery;
	u64 exit_qualification;
	u64 guest_linear_address;
	u64 guest_physical_address;
	u16 eptp_index;
};

#endif
+13 −0
Original line number Diff line number Diff line
@@ -95,6 +95,19 @@ config KVM_INTEL
	  To compile this as a module, choose M here: the module
	  will be called kvm-intel.

config KVM_INTEL_PROVE_VE
        bool "Check that guests do not receive #VE exceptions"
        default KVM_PROVE_MMU || DEBUG_KERNEL
        depends on KVM_INTEL
        help

          Checks that KVM's page table management code will not incorrectly
          let guests receive a virtualization exception.  Virtualization
          exceptions will be trapped by the hypervisor rather than injected
          in the guest.

          If unsure, say N.

config X86_SGX_KVM
	bool "Software Guard eXtensions (SGX) Virtualization"
	depends on X86_SGX && KVM_INTEL
+13 −8
Original line number Diff line number Diff line
@@ -567,9 +567,9 @@ static u64 mmu_spte_clear_track_bits(struct kvm *kvm, u64 *sptep)

	if (!is_shadow_present_pte(old_spte) ||
	    !spte_has_volatile_bits(old_spte))
		__update_clear_spte_fast(sptep, 0ull);
		__update_clear_spte_fast(sptep, SHADOW_NONPRESENT_VALUE);
	else
		old_spte = __update_clear_spte_slow(sptep, 0ull);
		old_spte = __update_clear_spte_slow(sptep, SHADOW_NONPRESENT_VALUE);

	if (!is_shadow_present_pte(old_spte))
		return old_spte;
@@ -603,7 +603,7 @@ static u64 mmu_spte_clear_track_bits(struct kvm *kvm, u64 *sptep)
 */
static void mmu_spte_clear_no_track(u64 *sptep)
{
	__update_clear_spte_fast(sptep, 0ull);
	__update_clear_spte_fast(sptep, SHADOW_NONPRESENT_VALUE);
}

static u64 mmu_spte_get_lockless(u64 *sptep)
@@ -1897,7 +1897,8 @@ static bool kvm_sync_page_check(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)

static int kvm_sync_spte(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp, int i)
{
	if (!sp->spt[i])
	/* sp->spt[i] has initial value of shadow page table allocation */
	if (sp->spt[i] == SHADOW_NONPRESENT_VALUE)
		return 0;

	return vcpu->arch.mmu->sync_spte(vcpu, sp, i);
@@ -2461,7 +2462,7 @@ static int mmu_page_zap_pte(struct kvm *kvm, struct kvm_mmu_page *sp,
				return kvm_mmu_prepare_zap_page(kvm, child,
								invalid_list);
		}
	} else if (is_mmio_spte(pte)) {
	} else if (is_mmio_spte(kvm, pte)) {
		mmu_spte_clear_no_track(spte);
	}
	return 0;
@@ -4143,7 +4144,7 @@ static int handle_mmio_page_fault(struct kvm_vcpu *vcpu, u64 addr, bool direct)
	if (WARN_ON_ONCE(reserved))
		return -EINVAL;

	if (is_mmio_spte(spte)) {
	if (is_mmio_spte(vcpu->kvm, spte)) {
		gfn_t gfn = get_mmio_spte_gfn(spte);
		unsigned int access = get_mmio_spte_access(spte);

@@ -4759,7 +4760,7 @@ EXPORT_SYMBOL_GPL(kvm_mmu_new_pgd);
static bool sync_mmio_spte(struct kvm_vcpu *vcpu, u64 *sptep, gfn_t gfn,
			   unsigned int access)
{
	if (unlikely(is_mmio_spte(*sptep))) {
	if (unlikely(is_mmio_spte(vcpu->kvm, *sptep))) {
		if (gfn != get_mmio_spte_gfn(*sptep)) {
			mmu_spte_clear_no_track(sptep);
			return true;
@@ -6120,6 +6121,9 @@ int kvm_mmu_create(struct kvm_vcpu *vcpu)
	vcpu->arch.mmu_page_header_cache.kmem_cache = mmu_page_header_cache;
	vcpu->arch.mmu_page_header_cache.gfp_zero = __GFP_ZERO;

	vcpu->arch.mmu_shadow_page_cache.init_value =
		SHADOW_NONPRESENT_VALUE;
	if (!vcpu->arch.mmu_shadow_page_cache.init_value)
		vcpu->arch.mmu_shadow_page_cache.gfp_zero = __GFP_ZERO;

	vcpu->arch.mmu = &vcpu->arch.root_mmu;
@@ -6263,6 +6267,7 @@ static bool kvm_has_zapped_obsolete_pages(struct kvm *kvm)

void kvm_mmu_init_vm(struct kvm *kvm)
{
	kvm->arch.shadow_mmio_value = shadow_mmio_value;
	INIT_LIST_HEAD(&kvm->arch.active_mmu_pages);
	INIT_LIST_HEAD(&kvm->arch.zapped_obsolete_pages);
	INIT_LIST_HEAD(&kvm->arch.possible_nx_huge_pages);
+7 −7
Original line number Diff line number Diff line
@@ -911,7 +911,7 @@ static int FNAME(sync_spte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp, int
	gpa_t pte_gpa;
	gfn_t gfn;

	if (WARN_ON_ONCE(!sp->spt[i]))
	if (WARN_ON_ONCE(sp->spt[i] == SHADOW_NONPRESENT_VALUE))
		return 0;

	first_pte_gpa = FNAME(get_level1_sp_gpa)(sp);
@@ -933,13 +933,13 @@ static int FNAME(sync_spte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp, int
		return 0;

	/*
	 * Drop the SPTE if the new protections would result in a RWX=0
	 * SPTE or if the gfn is changing.  The RWX=0 case only affects
	 * EPT with execute-only support, i.e. EPT without an effective
	 * "present" bit, as all other paging modes will create a
	 * read-only SPTE if pte_access is zero.
	 * Drop the SPTE if the new protections result in no effective
	 * "present" bit or if the gfn is changing.  The former case
	 * only affects EPT with execute-only support with pte_access==0;
	 * all other paging modes will create a read-only SPTE if
	 * pte_access is zero.
	 */
	if ((!pte_access && !shadow_present_mask) ||
	if ((pte_access | shadow_present_mask) == SHADOW_NONPRESENT_VALUE ||
	    gfn != kvm_mmu_page_get_gfn(sp, i)) {
		drop_spte(vcpu->kvm, &sp->spt[i]);
		return 1;
Loading