Skip to content

Commit 837d557

Browse files
sean-jcbonzini
authored andcommitted
KVM: x86/mmu: Add sanity checks that KVM doesn't create EPT #VE SPTEs
Assert that KVM doesn't set a SPTE to a value that could trigger an EPT Violation #VE on a non-MMIO SPTE, e.g. to help detect bugs even without KVM_INTEL_PROVE_VE enabled, and to help debug actual #VE failures. Note, this will run afoul of TDX support, which needs to reflect emulated MMIO accesses into the guest as #VEs (which was the whole point of adding EPT Violation #VE support in KVM). The obvious fix for that is to exempt MMIO SPTEs, but that's annoyingly difficult now that is_mmio_spte() relies on a per-VM value. However, resolving that conundrum is a future problem, whereas getting KVM_INTEL_PROVE_VE healthy is a current problem. Signed-off-by: Sean Christopherson <[email protected]> Message-ID: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 9031b42 commit 837d557

File tree

3 files changed

+14
-0
lines changed

3 files changed

+14
-0
lines changed

arch/x86/kvm/mmu/mmu.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,16 +336,19 @@ static int is_cpuid_PSE36(void)
336336
#ifdef CONFIG_X86_64
337337
static void __set_spte(u64 *sptep, u64 spte)
338338
{
339+
KVM_MMU_WARN_ON(is_ept_ve_possible(spte));
339340
WRITE_ONCE(*sptep, spte);
340341
}
341342

342343
static void __update_clear_spte_fast(u64 *sptep, u64 spte)
343344
{
345+
KVM_MMU_WARN_ON(is_ept_ve_possible(spte));
344346
WRITE_ONCE(*sptep, spte);
345347
}
346348

347349
static u64 __update_clear_spte_slow(u64 *sptep, u64 spte)
348350
{
351+
KVM_MMU_WARN_ON(is_ept_ve_possible(spte));
349352
return xchg(sptep, spte);
350353
}
351354

arch/x86/kvm/mmu/spte.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#ifndef KVM_X86_MMU_SPTE_H
44
#define KVM_X86_MMU_SPTE_H
55

6+
#include <asm/vmx.h>
7+
68
#include "mmu.h"
79
#include "mmu_internal.h"
810

@@ -276,6 +278,13 @@ static inline bool is_shadow_present_pte(u64 pte)
276278
return !!(pte & SPTE_MMU_PRESENT_MASK);
277279
}
278280

281+
static inline bool is_ept_ve_possible(u64 spte)
282+
{
283+
return (shadow_present_mask & VMX_EPT_SUPPRESS_VE_BIT) &&
284+
!(spte & VMX_EPT_SUPPRESS_VE_BIT) &&
285+
(spte & VMX_EPT_RWX_MASK) != VMX_EPT_MISCONFIG_WX_VALUE;
286+
}
287+
279288
/*
280289
* Returns true if A/D bits are supported in hardware and are enabled by KVM.
281290
* When enabled, KVM uses A/D bits for all non-nested MMUs. Because L1 can

arch/x86/kvm/mmu/tdp_iter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ static inline u64 kvm_tdp_mmu_read_spte(tdp_ptep_t sptep)
2121

2222
static inline u64 kvm_tdp_mmu_write_spte_atomic(tdp_ptep_t sptep, u64 new_spte)
2323
{
24+
KVM_MMU_WARN_ON(is_ept_ve_possible(new_spte));
2425
return xchg(rcu_dereference(sptep), new_spte);
2526
}
2627

2728
static inline void __kvm_tdp_mmu_write_spte(tdp_ptep_t sptep, u64 new_spte)
2829
{
30+
KVM_MMU_WARN_ON(is_ept_ve_possible(new_spte));
2931
WRITE_ONCE(*rcu_dereference(sptep), new_spte);
3032
}
3133

0 commit comments

Comments
 (0)