]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: TDX: WARN if mirror SPTE doesn't have full RWX when creating S-EPT mapping
authorSean Christopherson <seanjc@google.com>
Thu, 30 Oct 2025 20:09:35 +0000 (13:09 -0700)
committerSean Christopherson <seanjc@google.com>
Wed, 5 Nov 2025 19:05:51 +0000 (11:05 -0800)
Pass in the mirror_spte to kvm_x86_ops.set_external_spte() to provide
symmetry with .remove_external_spte(), and assert in TDX that the mirror
SPTE is shadow-present with full RWX permissions (the TDX-Module doesn't
allow the hypervisor to control protections).

Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com>
Reviewed-by: Kai Huang <kai.huang@intel.com>
Reviewed-by: Yan Zhao <yan.y.zhao@intel.com>
Tested-by: Yan Zhao <yan.y.zhao@intel.com>
Tested-by: Kai Huang <kai.huang@intel.com>
Link: https://patch.msgid.link/20251030200951.3402865-13-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/mmu/tdp_mmu.c
arch/x86/kvm/vmx/tdx.c

index b5867f8fe6ce57a9be71aa3508d72f24298d6d3d..87a5f5100b1d7ec1ae33e4b8c34a3180d21f9ecd 100644 (file)
@@ -1848,7 +1848,7 @@ struct kvm_x86_ops {
                                void *external_spt);
        /* Update the external page table from spte getting set. */
        int (*set_external_spte)(struct kvm *kvm, gfn_t gfn, enum pg_level level,
-                                kvm_pfn_t pfn_for_gfn);
+                                u64 mirror_spte);
 
        /* Update external page tables for page table about to be freed. */
        int (*free_external_spt)(struct kvm *kvm, gfn_t gfn, enum pg_level level,
index e1a96e9ea1bbc9ab7b9a138dd3ac89a72ebf8cba..9c26038f6b77ec84287046f408a6b8d8a314f3f2 100644 (file)
@@ -515,7 +515,6 @@ static int __must_check set_external_spte_present(struct kvm *kvm, tdp_ptep_t sp
        bool was_present = is_shadow_present_pte(old_spte);
        bool is_present = is_shadow_present_pte(new_spte);
        bool is_leaf = is_present && is_last_spte(new_spte, level);
-       kvm_pfn_t new_pfn = spte_to_pfn(new_spte);
        int ret = 0;
 
        KVM_BUG_ON(was_present, kvm);
@@ -534,7 +533,7 @@ static int __must_check set_external_spte_present(struct kvm *kvm, tdp_ptep_t sp
         * external page table, or leaf.
         */
        if (is_leaf) {
-               ret = kvm_x86_call(set_external_spte)(kvm, gfn, level, new_pfn);
+               ret = kvm_x86_call(set_external_spte)(kvm, gfn, level, new_spte);
        } else {
                void *external_spt = get_external_spt(gfn, new_spte, level);
 
index 247c35164565f22a2706cd8cfbdc8b4b32e9ea94..1315fd9fdd6e9dbec96b9383b683097ea052973d 100644 (file)
@@ -1629,14 +1629,18 @@ static int tdx_mem_page_record_premap_cnt(struct kvm *kvm, gfn_t gfn,
 }
 
 static int tdx_sept_set_private_spte(struct kvm *kvm, gfn_t gfn,
-                                    enum pg_level level, kvm_pfn_t pfn)
+                                    enum pg_level level, u64 mirror_spte)
 {
        struct kvm_tdx *kvm_tdx = to_kvm_tdx(kvm);
+       kvm_pfn_t pfn = spte_to_pfn(mirror_spte);
 
        /* TODO: handle large pages. */
        if (KVM_BUG_ON(level != PG_LEVEL_4K, kvm))
                return -EIO;
 
+       WARN_ON_ONCE(!is_shadow_present_pte(mirror_spte) ||
+                    (mirror_spte & VMX_EPT_RWX_MASK) != VMX_EPT_RWX_MASK);
+
        /*
         * Read 'pre_fault_allowed' before 'kvm_tdx->state'; see matching
         * barrier in tdx_td_finalize().