From: Sasha Levin Date: Tue, 30 Jun 2026 15:47:12 +0000 (-0400) Subject: Drop some KVM patches from 5.15 X-Git-Tag: v5.10.260~62 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f0d8769d57981552b47c0fdc476643560fe33aff;p=thirdparty%2Fkernel%2Fstable-queue.git Drop some KVM patches from 5.15 Signed-off-by: Sasha Levin --- diff --git a/queue-5.15/kvm-x86-fix-shadow-paging-use-after-free-due-to-unex.patch b/queue-5.15/kvm-x86-fix-shadow-paging-use-after-free-due-to-unex.patch deleted file mode 100644 index 589f8850d3..0000000000 --- a/queue-5.15/kvm-x86-fix-shadow-paging-use-after-free-due-to-unex.patch +++ /dev/null @@ -1,153 +0,0 @@ -From c5187da0baea9ce4ae374f34426c36ca619aa217 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Fri, 26 Jun 2026 19:46:17 +0200 -Subject: KVM: x86: Fix shadow paging use-after-free due to unexpected GFN - -From: Sean Christopherson - -commit 0cb2af2ea66ad8ff195c156ea690f11216285bdf upstream. - -The shadow MMU computes GFNs for direct shadow pages using sp->gfn plus -the SPTE index. This assumption breaks for shadow paging if the guest -page tables are modified between VM entries (similar to commit -aad885e77496, "KVM: x86/mmu: Drop/zap existing present SPTE even -when creating an MMIO SPTE", 2026-03-27). The flow is as follows: - -- a PDE is installed for a 2MB mapping, and a page in that area is - accessed. KVM creates a kvm_mmu_page consisting of 512 4KB pages; - the kvm_mmu_page is marked by FNAME(fetch) as direct-mapped because - the guest's mapping is a huge page (and thus contiguous). - -- the PDE mapping is changed from outside the guest. - -- the guest accesses another page in the same 2MB area. KVM installs - a new leaf SPTE and rmap entry; the SPTE uses the "correct" GFN - (i.e. based on the new mapping, as changed in the previous step) but - that GFN is outside of the [sp->gfn, sp->gfn + 511] range; therefore - the rmap entry cannot be found and removed when the kvm_mmu_page - is zapped. - -- the memslot that covers the first 2MB mapping is deleted, and the - kvm_mmu_page for the now-invalid GPA is zapped. However, rmap_remove() - only looks at the [sp->gfn, sp->gfn + 511] range established in step 1, - and fails to find the rmap entry that was recorded by step 3. - -- any operation that causes an rmap walk for the same page accessed - by step 3 then walks a stale rmap and dereferences a freed kvm_mmu_page. - This includes dirty logging or MMU notifier invalidations (e.g., from - MADV_DONTNEED). - -The underlying issue is that KVM's walking of shadow PTEs assumes that -if a SPTE is present when KVM wants to install a non-leaf SPTE, then the -existing kvm_mmu_page must be for the correct gfn. Because the only way -for the gfn to be wrong is if KVM messed up and failed to zap a SPTE... -which shouldn't happen, but *actually* only happens in response to a -guest write. - -That bug dates back literally forever, as even the first version of KVM -assumes that the GFN matches and walks into the "wrong" shadow page. -However, that was only an imprecision until 2032a93d66fa ("KVM: MMU: -Don't allocate gfns page for direct mmu pages") came along. - -Fix it by checking for a target gfn mismatch and zapping the existing -SPTE. That way the old SP and rmap entries are gone, KVM installs -the rmap in the right location, and everyone is happy. - -Fixes: 2032a93d66fa ("KVM: MMU: Don't allocate gfns page for direct mmu pages") -Fixes: 6aa8b732ca01 ("kvm: userspace interface") -Reported-by: Alexander Bulekov -Reported-by: Fred Griffoul -Cc: stable@vger.kernel.org -Signed-off-by: Sean Christopherson -Link: https://patch.msgid.link/20260503201029.106481-1-pbonzini@redhat.com/ -Signed-off-by: Paolo Bonzini -Signed-off-by: Sasha Levin ---- - arch/x86/kvm/mmu/mmu.c | 33 ++++++++++++++------------------- - arch/x86/kvm/mmu/spte.h | 5 +++++ - 2 files changed, 19 insertions(+), 19 deletions(-) - -diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c -index d58be2e698f795..6c9656b8062e4e 100644 ---- a/arch/x86/kvm/mmu/mmu.c -+++ b/arch/x86/kvm/mmu/mmu.c -@@ -188,6 +188,8 @@ static struct percpu_counter kvm_total_used_mmu_pages; - static void mmu_spte_set(u64 *sptep, u64 spte); - static union kvm_mmu_page_role - kvm_mmu_calc_root_page_role(struct kvm_vcpu *vcpu); -+static int mmu_page_zap_pte(struct kvm *kvm, struct kvm_mmu_page *sp, -+ u64 *spte, struct list_head *invalid_list); - - struct kvm_mmu_role_regs { - const unsigned long cr0; -@@ -1179,18 +1181,6 @@ static void drop_spte(struct kvm *kvm, u64 *sptep) - rmap_remove(kvm, sptep); - } - --static void drop_large_spte(struct kvm *kvm, u64 *sptep) --{ -- struct kvm_mmu_page *sp; -- -- sp = sptep_to_sp(sptep); -- WARN_ON(sp->role.level == PG_LEVEL_4K); -- -- drop_spte(kvm, sptep); -- kvm_flush_remote_tlbs_with_address(kvm, sp->gfn, -- KVM_PAGES_PER_HPAGE(sp->role.level)); --} -- - /* - * Write-protect on the specified @sptep, @pt_protect indicates whether - * spte write-protection is caused by protecting shadow page table. -@@ -2187,7 +2177,8 @@ static struct kvm_mmu_page *kvm_mmu_get_child_sp(struct kvm_vcpu *vcpu, - { - union kvm_mmu_page_role role; - -- if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep)) -+ if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep) && -+ spte_to_child_sp(*sptep) && spte_to_child_sp(*sptep)->gfn == gfn) - return ERR_PTR(-EEXIST); - - role = kvm_mmu_child_role(sptep, direct, access); -@@ -2265,12 +2256,16 @@ static void __link_shadow_page(struct kvm_vcpu *vcpu, - - BUILD_BUG_ON(VMX_EPT_WRITABLE_MASK != PT_WRITABLE_MASK); - -- /* -- * If an SPTE is present already, it must be a leaf and therefore -- * a large one. Drop it and flush the TLB before installing sp. -- */ -- if (is_shadow_present_pte(*sptep)) -- drop_large_spte(vcpu->kvm, sptep); -+ if (is_shadow_present_pte(*sptep)) { -+ struct kvm_mmu_page *parent_sp; -+ LIST_HEAD(invalid_list); -+ -+ parent_sp = sptep_to_sp(sptep); -+ WARN_ON_ONCE(parent_sp->role.level == PG_LEVEL_4K); -+ -+ mmu_page_zap_pte(vcpu->kvm, parent_sp, sptep, &invalid_list); -+ kvm_mmu_remote_flush_or_zap(vcpu->kvm, &invalid_list, true); -+ } - - spte = make_nonleaf_spte(sp->spt, sp_ad_disabled(sp)); - -diff --git a/arch/x86/kvm/mmu/spte.h b/arch/x86/kvm/mmu/spte.h -index 31d6456d8ac333..31d03d15415c01 100644 ---- a/arch/x86/kvm/mmu/spte.h -+++ b/arch/x86/kvm/mmu/spte.h -@@ -267,6 +267,11 @@ static inline bool is_executable_pte(u64 spte) - return (spte & (shadow_x_mask | shadow_nx_mask)) == shadow_x_mask; - } - -+static inline struct kvm_mmu_page *spte_to_child_sp(u64 spte) -+{ -+ return to_shadow_page(spte & PT64_BASE_ADDR_MASK); -+} -+ - static inline kvm_pfn_t spte_to_pfn(u64 pte) - { - return (pte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT; --- -2.53.0 - diff --git a/queue-5.15/kvm-x86-fix-shadow-paging-use-after-free-due-to-unex.patch-23529 b/queue-5.15/kvm-x86-fix-shadow-paging-use-after-free-due-to-unex.patch-23529 deleted file mode 100644 index 772f811e1b..0000000000 --- a/queue-5.15/kvm-x86-fix-shadow-paging-use-after-free-due-to-unex.patch-23529 +++ /dev/null @@ -1,71 +0,0 @@ -From 6d15eee7dcdbc7794d7e83bb36847eeeea7d4938 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Fri, 26 Jun 2026 19:46:18 +0200 -Subject: KVM: x86: Fix shadow paging use-after-free due to unexpected role - -From: Paolo Bonzini - -[ Upstream commit 81ccda30b4e83d8f5cc4fd50503c44e3a33abfeb ] - -Commit 0cb2af2ea66ad ("KVM: x86: Fix shadow paging use-after-free due -to unexpected GFN") fixed a shadow paging mismatch between stored and -computed GFNs; the bug could be triggered by changing a PDE mapping from -outside the guest, and then deleting a memslot. The rmap_remove() -call would miss entries created after the PDE change because the GFN -of the leaf SPTE does not match the GFN of the struct kvm_mmu_page. - -A similar hole however remains if the modified PDE points to a non-leaf -page. In this case the gfn can be made to match, but the role does not -match: the original large 2MB page creates a kvm_mmu_page with direct=1, -while the new 4KB needs a kvm_mmu_page with direct=0. However, -kvm_mmu_get_child_sp() does not compare the role, and therefore reuses -the page. - -The next step is installing a leaf (4KB) SPTE on the new path which -records an rmap entry under the gfn resolved by the walk. But when -that child is zapped its parent kvm_mmu_page has direct=1 and -kvm_mmu_page_get_gfn() computes the gfn for the 4KB page as -sp->gfn + index instead of using sp->shadowed_translation[] (or sp->gfns[] -in older kernels). It therefore fails to remove the recorded entry. - -When the memslot is dropped the shadow page is freed but the rmap -entry survives, as in the scenario that was already fixed. Code that -later walks that gfn (dirty logging, MMU notifier invalidation, and -so on) dereferences an sptep that lies in the freed page, causing the -use-after-free. - -Fixes: 2032a93d66fa ("KVM: MMU: Don't allocate gfns page for direct mmu pages") -Reported-by: Hyunwoo Kim -Signed-off-by: Paolo Bonzini -Signed-off-by: Sasha Levin ---- - arch/x86/kvm/mmu/mmu.c | 10 ++++++---- - 1 file changed, 6 insertions(+), 4 deletions(-) - -diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c -index 6c9656b8062e4e..e9dbe3e7ec622f 100644 ---- a/arch/x86/kvm/mmu/mmu.c -+++ b/arch/x86/kvm/mmu/mmu.c -@@ -2175,13 +2175,15 @@ static struct kvm_mmu_page *kvm_mmu_get_child_sp(struct kvm_vcpu *vcpu, - u64 *sptep, gfn_t gfn, - bool direct, unsigned int access) - { -- union kvm_mmu_page_role role; -+ union kvm_mmu_page_role role = kvm_mmu_child_role(sptep, direct, access); - -- if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep) && -- spte_to_child_sp(*sptep) && spte_to_child_sp(*sptep)->gfn == gfn) -+ if (is_shadow_present_pte(*sptep) && -+ !is_large_pte(*sptep) && -+ spte_to_child_sp(*sptep) && -+ spte_to_child_sp(*sptep)->gfn == gfn && -+ spte_to_child_sp(*sptep)->role.word == role.word) - return ERR_PTR(-EEXIST); - -- role = kvm_mmu_child_role(sptep, direct, access); - return kvm_mmu_get_page(vcpu, gfn, role); - } - --- -2.53.0 - diff --git a/queue-5.15/kvm-x86-mmu-always-pass-0-for-quadrant-when-gptes-ar.patch b/queue-5.15/kvm-x86-mmu-always-pass-0-for-quadrant-when-gptes-ar.patch deleted file mode 100644 index b3502dca3e..0000000000 --- a/queue-5.15/kvm-x86-mmu-always-pass-0-for-quadrant-when-gptes-ar.patch +++ /dev/null @@ -1,79 +0,0 @@ -From cd2b29b10c0f8055c823c5df970fb98e897f65b9 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Fri, 26 Jun 2026 19:46:15 +0200 -Subject: KVM: x86/mmu: Always pass 0 for @quadrant when gptes are 8 bytes - -From: Paolo Bonzini - -commit 7f49777550e55a7d6832cbb0873f48f91c175b9c upstream. - -The quadrant is only used when gptes are 4 bytes, but -mmu_alloc_{direct,shadow}_roots() pass in a non-zero quadrant for PAE -page directories regardless. Make this less confusing by only passing in -a non-zero quadrant when it is actually necessary. - -Signed-off-by: David Matlack -Message-Id: <20220516232138.1783324-6-dmatlack@google.com> -Signed-off-by: Paolo Bonzini -Signed-off-by: Sasha Levin ---- - arch/x86/kvm/mmu/mmu.c | 20 ++++++++++++++------ - 1 file changed, 14 insertions(+), 6 deletions(-) - -diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c -index 3a5ed967037765..dbc18d4cc572c1 100644 ---- a/arch/x86/kvm/mmu/mmu.c -+++ b/arch/x86/kvm/mmu/mmu.c -@@ -3444,9 +3444,10 @@ static hpa_t mmu_alloc_root(struct kvm_vcpu *vcpu, gfn_t gfn, int quadrant, - struct kvm_mmu_page *sp; - - role.level = level; -+ role.quadrant = quadrant; - -- if (!role.gpte_is_8_bytes) -- role.quadrant = quadrant; -+ WARN_ON_ONCE(quadrant && role.gpte_is_8_bytes); -+ WARN_ON_ONCE(role.direct && !role.gpte_is_8_bytes); - - sp = kvm_mmu_get_page(vcpu, gfn, role); - ++sp->root_count; -@@ -3482,7 +3483,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu) - for (i = 0; i < 4; ++i) { - WARN_ON_ONCE(IS_VALID_PAE_ROOT(mmu->pae_root[i])); - -- root = mmu_alloc_root(vcpu, i << (30 - PAGE_SHIFT), i, -+ root = mmu_alloc_root(vcpu, i << (30 - PAGE_SHIFT), 0, - PT32_ROOT_LEVEL); - mmu->pae_root[i] = root | PT_PRESENT_MASK | - shadow_me_mask; -@@ -3506,9 +3507,8 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu) - struct kvm_mmu *mmu = vcpu->arch.mmu; - u64 pdptrs[4], pm_mask; - gfn_t root_gfn, root_pgd; -+ int quadrant, i, r; - hpa_t root; -- unsigned i; -- int r; - - root_pgd = mmu->get_guest_pgd(vcpu); - root_gfn = root_pgd >> PAGE_SHIFT; -@@ -3591,7 +3591,15 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu) - root_gfn = pdptrs[i] >> PAGE_SHIFT; - } - -- root = mmu_alloc_root(vcpu, root_gfn, i, PT32_ROOT_LEVEL); -+ /* -+ * If shadowing 32-bit non-PAE page tables, each PAE page -+ * directory maps one quarter of the guest's non-PAE page -+ * directory. Othwerise each PAE page direct shadows one guest -+ * PAE page directory so that quadrant should be 0. -+ */ -+ quadrant = !mmu->mmu_role.base.gpte_is_8_bytes ? i : 0; -+ -+ root = mmu_alloc_root(vcpu, root_gfn, quadrant, PT32_ROOT_LEVEL); - mmu->pae_root[i] = root | pm_mask; - } - --- -2.53.0 - diff --git a/queue-5.15/kvm-x86-mmu-derive-shadow-mmu-page-role-from-parent.patch b/queue-5.15/kvm-x86-mmu-derive-shadow-mmu-page-role-from-parent.patch deleted file mode 100644 index 77edb26340..0000000000 --- a/queue-5.15/kvm-x86-mmu-derive-shadow-mmu-page-role-from-parent.patch +++ /dev/null @@ -1,240 +0,0 @@ -From 3776b66e4f8c1d6c8b888792cf8a31987b316bd6 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Fri, 26 Jun 2026 19:46:14 +0200 -Subject: KVM: x86/mmu: Derive shadow MMU page role from parent - -From: Paolo Bonzini - -commit 2e65e842c57d72e9a573ba42bc2055b7f626ea1f upstream. - -Instead of computing the shadow page role from scratch for every new -page, derive most of the information from the parent shadow page. This -eliminates the dependency on the vCPU root role to allocate shadow page -tables, and reduces the number of parameters to kvm_mmu_get_page(). - -Preemptively split out the role calculation to a separate function for -use in a following commit. - -Note that when calculating the MMU root role, we can take -@role.passthrough, @role.direct, and @role.access directly from -@vcpu->arch.mmu->root_role. Only @role.level and @role.quadrant still -must be overridden for PAE page directories, when shadowing 32-bit -guest page tables with PAE page tables. - -No functional change intended. - -Reviewed-by: Peter Xu -Signed-off-by: David Matlack -Message-Id: <20220516232138.1783324-5-dmatlack@google.com> -Signed-off-by: Paolo Bonzini -Signed-off-by: Sasha Levin ---- - arch/x86/kvm/mmu/mmu.c | 99 ++++++++++++++++++++++------------ - arch/x86/kvm/mmu/paging_tmpl.h | 9 ++-- - 2 files changed, 71 insertions(+), 37 deletions(-) - -diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c -index bd7650380ad9e7..3a5ed967037765 100644 ---- a/arch/x86/kvm/mmu/mmu.c -+++ b/arch/x86/kvm/mmu/mmu.c -@@ -2070,33 +2070,15 @@ static void clear_sp_write_flooding_count(u64 *spte) - __clear_sp_write_flooding_count(sptep_to_sp(spte)); - } - --static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, -- gfn_t gfn, -- gva_t gaddr, -- unsigned level, -- bool direct, -- unsigned int access) -+static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, gfn_t gfn, -+ union kvm_mmu_page_role role) - { - bool direct_mmu = vcpu->arch.mmu->direct_map; -- union kvm_mmu_page_role role; - struct hlist_head *sp_list; -- unsigned quadrant; - struct kvm_mmu_page *sp; - int collisions = 0; - LIST_HEAD(invalid_list); - -- role = vcpu->arch.mmu->mmu_role.base; -- role.level = level; -- role.direct = direct; -- if (role.direct) -- role.gpte_is_8_bytes = true; -- role.access = access; -- if (!direct_mmu && vcpu->arch.mmu->root_level <= PT32_ROOT_LEVEL) { -- quadrant = gaddr >> (PAGE_SHIFT + (PT64_PT_BITS * level)); -- quadrant &= (1 << ((PT32_PT_BITS - PT64_PT_BITS) * level)) - 1; -- role.quadrant = quadrant; -- } -- - sp_list = &vcpu->kvm->arch.mmu_page_hash[kvm_page_table_hashfn(gfn)]; - for_each_valid_sp(vcpu->kvm, sp, sp_list) { - if (sp->gfn != gfn) { -@@ -2114,7 +2096,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, - * Unsync pages must not be left as is, because the new - * upper-level page will be write-protected. - */ -- if (level > PG_LEVEL_4K && sp->unsync) -+ if (role.level > PG_LEVEL_4K && sp->unsync) - kvm_mmu_prepare_zap_page(vcpu->kvm, sp, - &invalid_list); - continue; -@@ -2152,14 +2134,14 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, - - ++vcpu->kvm->stat.mmu_cache_miss; - -- sp = kvm_mmu_alloc_page(vcpu, direct); -+ sp = kvm_mmu_alloc_page(vcpu, role.direct); - - sp->gfn = gfn; - sp->role = role; - hlist_add_head(&sp->hash_link, sp_list); -- if (!direct) { -+ if (!role.direct) { - account_shadowed(vcpu->kvm, sp); -- if (level == PG_LEVEL_4K && rmap_write_protect(vcpu, gfn)) -+ if (role.level == PG_LEVEL_4K && rmap_write_protect(vcpu, gfn)) - kvm_flush_remote_tlbs_with_address(vcpu->kvm, gfn, 1); - } - trace_kvm_mmu_get_page(sp, true); -@@ -2171,6 +2153,54 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, - return sp; - } - -+static union kvm_mmu_page_role kvm_mmu_child_role(u64 *sptep, bool direct, unsigned int access) -+{ -+ struct kvm_mmu_page *parent_sp = sptep_to_sp(sptep); -+ union kvm_mmu_page_role role; -+ -+ role = parent_sp->role; -+ role.level--; -+ role.access = access; -+ role.direct = direct; -+ -+ /* -+ * If the guest has 4-byte PTEs then that means it's using 32-bit, -+ * 2-level, non-PAE paging. KVM shadows such guests with PAE paging -+ * (i.e. 8-byte PTEs). The difference in PTE size means that KVM must -+ * shadow each guest page table with multiple shadow page tables, which -+ * requires extra bookkeeping in the role. -+ * -+ * Specifically, to shadow the guest's page directory (which covers a -+ * 4GiB address space), KVM uses 4 PAE page directories, each mapping -+ * 1GiB of the address space. @role.quadrant encodes which quarter of -+ * the address space each maps. -+ * -+ * To shadow the guest's page tables (which each map a 4MiB region), KVM -+ * uses 2 PAE page tables, each mapping a 2MiB region. For these, -+ * @role.quadrant encodes which half of the region they map. -+ * -+ * Note, the 4 PAE page directories are pre-allocated and the quadrant -+ * assigned in mmu_alloc_root(). So only page tables need to be handled -+ * here. -+ */ -+ if (!role.gpte_is_8_bytes) { -+ WARN_ON_ONCE(role.level != PG_LEVEL_4K); -+ role.quadrant = (sptep - parent_sp->spt) % 2; -+ } -+ -+ return role; -+} -+ -+static struct kvm_mmu_page *kvm_mmu_get_child_sp(struct kvm_vcpu *vcpu, -+ u64 *sptep, gfn_t gfn, -+ bool direct, unsigned int access) -+{ -+ union kvm_mmu_page_role role; -+ -+ role = kvm_mmu_child_role(sptep, direct, access); -+ return kvm_mmu_get_page(vcpu, gfn, role); -+} -+ - static void shadow_walk_init_using_root(struct kvm_shadow_walk_iterator *iterator, - struct kvm_vcpu *vcpu, hpa_t root, - u64 addr) -@@ -3013,8 +3043,7 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code, - if (is_shadow_present_pte(*it.sptep)) - continue; - -- sp = kvm_mmu_get_page(vcpu, base_gfn, it.addr, -- it.level - 1, true, ACC_ALL); -+ sp = kvm_mmu_get_child_sp(vcpu, it.sptep, base_gfn, true, ACC_ALL); - - link_shadow_page(vcpu, it.sptep, sp); - if (is_tdp && huge_page_disallowed && -@@ -3408,13 +3437,18 @@ static int mmu_check_root(struct kvm_vcpu *vcpu, gfn_t root_gfn) - return ret; - } - --static hpa_t mmu_alloc_root(struct kvm_vcpu *vcpu, gfn_t gfn, gva_t gva, -+static hpa_t mmu_alloc_root(struct kvm_vcpu *vcpu, gfn_t gfn, int quadrant, - u8 level) - { -- bool direct = vcpu->arch.mmu->mmu_role.base.direct; -+ union kvm_mmu_page_role role = vcpu->arch.mmu->mmu_role.base; - struct kvm_mmu_page *sp; - -- sp = kvm_mmu_get_page(vcpu, gfn, gva, level, direct, ACC_ALL); -+ role.level = level; -+ -+ if (!role.gpte_is_8_bytes) -+ role.quadrant = quadrant; -+ -+ sp = kvm_mmu_get_page(vcpu, gfn, role); - ++sp->root_count; - - return __pa(sp->spt); -@@ -3448,8 +3482,8 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu) - for (i = 0; i < 4; ++i) { - WARN_ON_ONCE(IS_VALID_PAE_ROOT(mmu->pae_root[i])); - -- root = mmu_alloc_root(vcpu, i << (30 - PAGE_SHIFT), -- i << 30, PT32_ROOT_LEVEL); -+ root = mmu_alloc_root(vcpu, i << (30 - PAGE_SHIFT), i, -+ PT32_ROOT_LEVEL); - mmu->pae_root[i] = root | PT_PRESENT_MASK | - shadow_me_mask; - } -@@ -3557,8 +3591,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu) - root_gfn = pdptrs[i] >> PAGE_SHIFT; - } - -- root = mmu_alloc_root(vcpu, root_gfn, i << 30, -- PT32_ROOT_LEVEL); -+ root = mmu_alloc_root(vcpu, root_gfn, i, PT32_ROOT_LEVEL); - mmu->pae_root[i] = root | pm_mask; - } - -diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h -index a1811f51eda925..cc70cbb3f261ba 100644 ---- a/arch/x86/kvm/mmu/paging_tmpl.h -+++ b/arch/x86/kvm/mmu/paging_tmpl.h -@@ -704,8 +704,9 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gpa_t addr, - if (!is_shadow_present_pte(*it.sptep)) { - table_gfn = gw->table_gfn[it.level - 2]; - access = gw->pt_access[it.level - 2]; -- sp = kvm_mmu_get_page(vcpu, table_gfn, addr, -- it.level-1, false, access); -+ sp = kvm_mmu_get_child_sp(vcpu, it.sptep, table_gfn, -+ false, access); -+ - /* - * We must synchronize the pagetable before linking it - * because the guest doesn't need to flush tlb when -@@ -763,8 +764,8 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gpa_t addr, - drop_large_spte(vcpu, it.sptep); - - if (!is_shadow_present_pte(*it.sptep)) { -- sp = kvm_mmu_get_page(vcpu, base_gfn, addr, -- it.level - 1, true, direct_access); -+ sp = kvm_mmu_get_child_sp(vcpu, it.sptep, base_gfn, -+ true, direct_access); - link_shadow_page(vcpu, it.sptep, sp); - if (huge_page_disallowed && req_level >= it.level) - account_huge_nx_page(vcpu->kvm, sp); --- -2.53.0 - diff --git a/queue-5.15/kvm-x86-mmu-pull-call-to-drop_large_spte-into-__link.patch b/queue-5.15/kvm-x86-mmu-pull-call-to-drop_large_spte-into-__link.patch deleted file mode 100644 index 920b801fcd..0000000000 --- a/queue-5.15/kvm-x86-mmu-pull-call-to-drop_large_spte-into-__link.patch +++ /dev/null @@ -1,193 +0,0 @@ -From bcc6397d244844807014d82fa65afa416d431f0b Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Fri, 26 Jun 2026 19:46:16 +0200 -Subject: KVM: x86/mmu: pull call to drop_large_spte() into - __link_shadow_page() - -From: Paolo Bonzini - -commit 0cd8dc739833080aa0813cbd94d907a93e3a14c3 upstream. - -Before allocating a child shadow page table, all callers check -whether the parent already points to a huge page and, if so, they -drop that SPTE. This is done by drop_large_spte(). - -However, dropping the large SPTE is really only necessary before the -sp is installed. While the sp is returned by kvm_mmu_get_child_sp(), -installing it happens later in __link_shadow_page(). Move the call -there instead of having it in each and every caller. - -To ensure that the shadow page is not linked twice if it was present, -do _not_ opportunistically make kvm_mmu_get_child_sp() idempotent: -instead, return an error value if the shadow page already existed. -This is a bit more verbose, but clearer than NULL. - -Finally, now that the drop_large_spte() name is not taken anymore, -remove the two underscores in front of __drop_large_spte(). - -Reviewed-by: Sean Christopherson -Signed-off-by: Paolo Bonzini -Signed-off-by: Sasha Levin ---- - arch/x86/kvm/mmu/mmu.c | 49 +++++++++++++++++++--------------- - arch/x86/kvm/mmu/paging_tmpl.h | 29 +++++++++----------- - 2 files changed, 40 insertions(+), 38 deletions(-) - -diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c -index dbc18d4cc572c1..d58be2e698f795 100644 ---- a/arch/x86/kvm/mmu/mmu.c -+++ b/arch/x86/kvm/mmu/mmu.c -@@ -1179,26 +1179,16 @@ static void drop_spte(struct kvm *kvm, u64 *sptep) - rmap_remove(kvm, sptep); - } - -- --static bool __drop_large_spte(struct kvm *kvm, u64 *sptep) -+static void drop_large_spte(struct kvm *kvm, u64 *sptep) - { -- if (is_large_pte(*sptep)) { -- WARN_ON(sptep_to_sp(sptep)->role.level == PG_LEVEL_4K); -- drop_spte(kvm, sptep); -- return true; -- } -- -- return false; --} -+ struct kvm_mmu_page *sp; - --static void drop_large_spte(struct kvm_vcpu *vcpu, u64 *sptep) --{ -- if (__drop_large_spte(vcpu->kvm, sptep)) { -- struct kvm_mmu_page *sp = sptep_to_sp(sptep); -+ sp = sptep_to_sp(sptep); -+ WARN_ON(sp->role.level == PG_LEVEL_4K); - -- kvm_flush_remote_tlbs_with_address(vcpu->kvm, sp->gfn, -+ drop_spte(kvm, sptep); -+ kvm_flush_remote_tlbs_with_address(kvm, sp->gfn, - KVM_PAGES_PER_HPAGE(sp->role.level)); -- } - } - - /* -@@ -2197,6 +2187,9 @@ static struct kvm_mmu_page *kvm_mmu_get_child_sp(struct kvm_vcpu *vcpu, - { - union kvm_mmu_page_role role; - -+ if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep)) -+ return ERR_PTR(-EEXIST); -+ - role = kvm_mmu_child_role(sptep, direct, access); - return kvm_mmu_get_page(vcpu, gfn, role); - } -@@ -2264,13 +2257,21 @@ static void shadow_walk_next(struct kvm_shadow_walk_iterator *iterator) - __shadow_walk_next(iterator, *iterator->sptep); - } - --static void link_shadow_page(struct kvm_vcpu *vcpu, u64 *sptep, -- struct kvm_mmu_page *sp) -+static void __link_shadow_page(struct kvm_vcpu *vcpu, -+ struct kvm_mmu_memory_cache *cache, u64 *sptep, -+ struct kvm_mmu_page *sp) - { - u64 spte; - - BUILD_BUG_ON(VMX_EPT_WRITABLE_MASK != PT_WRITABLE_MASK); - -+ /* -+ * If an SPTE is present already, it must be a leaf and therefore -+ * a large one. Drop it and flush the TLB before installing sp. -+ */ -+ if (is_shadow_present_pte(*sptep)) -+ drop_large_spte(vcpu->kvm, sptep); -+ - spte = make_nonleaf_spte(sp->spt, sp_ad_disabled(sp)); - - mmu_spte_set(sptep, spte); -@@ -2281,6 +2282,12 @@ static void link_shadow_page(struct kvm_vcpu *vcpu, u64 *sptep, - mark_unsync(sptep); - } - -+static void link_shadow_page(struct kvm_vcpu *vcpu, u64 *sptep, -+ struct kvm_mmu_page *sp) -+{ -+ __link_shadow_page(vcpu, &vcpu->arch.mmu_pte_list_desc_cache, sptep, sp); -+} -+ - static void validate_direct_spte(struct kvm_vcpu *vcpu, u64 *sptep, - unsigned direct_access) - { -@@ -3039,11 +3046,9 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code, - if (it.level == level) - break; - -- drop_large_spte(vcpu, it.sptep); -- if (is_shadow_present_pte(*it.sptep)) -- continue; -- - sp = kvm_mmu_get_child_sp(vcpu, it.sptep, base_gfn, true, ACC_ALL); -+ if (sp == ERR_PTR(-EEXIST)) -+ continue; - - link_shadow_page(vcpu, it.sptep, sp); - if (is_tdp && huge_page_disallowed && -diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h -index cc70cbb3f261ba..0f68f5afa642c8 100644 ---- a/arch/x86/kvm/mmu/paging_tmpl.h -+++ b/arch/x86/kvm/mmu/paging_tmpl.h -@@ -698,15 +698,13 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gpa_t addr, - gfn_t table_gfn; - - clear_sp_write_flooding_count(it.sptep); -- drop_large_spte(vcpu, it.sptep); - -- sp = NULL; -- if (!is_shadow_present_pte(*it.sptep)) { -- table_gfn = gw->table_gfn[it.level - 2]; -- access = gw->pt_access[it.level - 2]; -- sp = kvm_mmu_get_child_sp(vcpu, it.sptep, table_gfn, -- false, access); -+ table_gfn = gw->table_gfn[it.level - 2]; -+ access = gw->pt_access[it.level - 2]; -+ sp = kvm_mmu_get_child_sp(vcpu, it.sptep, table_gfn, -+ false, access); - -+ if (sp != ERR_PTR(-EEXIST)) { - /* - * We must synchronize the pagetable before linking it - * because the guest doesn't need to flush tlb when -@@ -735,7 +733,7 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gpa_t addr, - if (FNAME(gpte_changed)(vcpu, gw, it.level - 1)) - goto out_gpte_changed; - -- if (sp) -+ if (sp != ERR_PTR(-EEXIST)) - link_shadow_page(vcpu, it.sptep, sp); - } - -@@ -761,15 +759,14 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gpa_t addr, - - validate_direct_spte(vcpu, it.sptep, direct_access); - -- drop_large_spte(vcpu, it.sptep); -+ sp = kvm_mmu_get_child_sp(vcpu, it.sptep, base_gfn, -+ true, direct_access); -+ if (sp == ERR_PTR(-EEXIST)) -+ continue; - -- if (!is_shadow_present_pte(*it.sptep)) { -- sp = kvm_mmu_get_child_sp(vcpu, it.sptep, base_gfn, -- true, direct_access); -- link_shadow_page(vcpu, it.sptep, sp); -- if (huge_page_disallowed && req_level >= it.level) -- account_huge_nx_page(vcpu->kvm, sp); -- } -+ link_shadow_page(vcpu, it.sptep, sp); -+ if (huge_page_disallowed && req_level >= it.level) -+ account_huge_nx_page(vcpu->kvm, sp); - } - - ret = mmu_set_spte(vcpu, it.sptep, gw->pte_access, write_fault, --- -2.53.0 - diff --git a/queue-5.15/kvm-x86-mmu-stop-passing-direct-to-mmu_alloc_root.patch b/queue-5.15/kvm-x86-mmu-stop-passing-direct-to-mmu_alloc_root.patch deleted file mode 100644 index ef4721eee6..0000000000 --- a/queue-5.15/kvm-x86-mmu-stop-passing-direct-to-mmu_alloc_root.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 18d012c4f2b01a72e0682e509dad85caf3248d11 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Fri, 26 Jun 2026 19:46:13 +0200 -Subject: KVM: x86/mmu: Stop passing "direct" to mmu_alloc_root() - -From: David Matlack - -commit 86938ab6925b8fe174ca6abf397e6ea9d3c054a4 upstream. - -The "direct" argument is vcpu->arch.mmu->root_role.direct, -because unlike non-root page tables, it's impossible to have -a direct root in an indirect MMU. So just use that. - -Suggested-by: Lai Jiangshan -Signed-off-by: David Matlack -Message-Id: <20220516232138.1783324-4-dmatlack@google.com> -Signed-off-by: Paolo Bonzini -Signed-off-by: Sasha Levin ---- - arch/x86/kvm/mmu/mmu.c | 11 ++++++----- - 1 file changed, 6 insertions(+), 5 deletions(-) - -diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c -index c03c4341a87fd7..bd7650380ad9e7 100644 ---- a/arch/x86/kvm/mmu/mmu.c -+++ b/arch/x86/kvm/mmu/mmu.c -@@ -3409,8 +3409,9 @@ static int mmu_check_root(struct kvm_vcpu *vcpu, gfn_t root_gfn) - } - - static hpa_t mmu_alloc_root(struct kvm_vcpu *vcpu, gfn_t gfn, gva_t gva, -- u8 level, bool direct) -+ u8 level) - { -+ bool direct = vcpu->arch.mmu->mmu_role.base.direct; - struct kvm_mmu_page *sp; - - sp = kvm_mmu_get_page(vcpu, gfn, gva, level, direct, ACC_ALL); -@@ -3436,7 +3437,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu) - root = kvm_tdp_mmu_get_vcpu_root_hpa(vcpu); - mmu->root_hpa = root; - } else if (shadow_root_level >= PT64_ROOT_4LEVEL) { -- root = mmu_alloc_root(vcpu, 0, 0, shadow_root_level, true); -+ root = mmu_alloc_root(vcpu, 0, 0, shadow_root_level); - mmu->root_hpa = root; - } else if (shadow_root_level == PT32E_ROOT_LEVEL) { - if (WARN_ON_ONCE(!mmu->pae_root)) { -@@ -3448,7 +3449,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu) - WARN_ON_ONCE(IS_VALID_PAE_ROOT(mmu->pae_root[i])); - - root = mmu_alloc_root(vcpu, i << (30 - PAGE_SHIFT), -- i << 30, PT32_ROOT_LEVEL, true); -+ i << 30, PT32_ROOT_LEVEL); - mmu->pae_root[i] = root | PT_PRESENT_MASK | - shadow_me_mask; - } -@@ -3511,7 +3512,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu) - */ - if (mmu->root_level >= PT64_ROOT_4LEVEL) { - root = mmu_alloc_root(vcpu, root_gfn, 0, -- mmu->shadow_root_level, false); -+ mmu->shadow_root_level); - mmu->root_hpa = root; - goto set_root_pgd; - } -@@ -3557,7 +3558,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu) - } - - root = mmu_alloc_root(vcpu, root_gfn, i << 30, -- PT32_ROOT_LEVEL, false); -+ PT32_ROOT_LEVEL); - mmu->pae_root[i] = root | pm_mask; - } - --- -2.53.0 - diff --git a/queue-5.15/kvm-x86-mmu-use-a-bool-for-direct.patch b/queue-5.15/kvm-x86-mmu-use-a-bool-for-direct.patch deleted file mode 100644 index 37981229e5..0000000000 --- a/queue-5.15/kvm-x86-mmu-use-a-bool-for-direct.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 88a03cd0c1f9927e56dc6fd8cb5dc4c44b2666d8 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Fri, 26 Jun 2026 19:46:12 +0200 -Subject: KVM: x86/mmu: Use a bool for direct - -From: David Matlack - -commit 27a59d57f073f21f029df1517c2c0a1abea5b0ce upstream. - -The parameter "direct" can either be true or false, and all of the -callers pass in a bool variable or true/false literal, so just use the -type bool. - -No functional change intended. - -Reviewed-by: Lai Jiangshan -Reviewed-by: Sean Christopherson -Signed-off-by: David Matlack -Message-Id: <20220516232138.1783324-3-dmatlack@google.com> -Signed-off-by: Paolo Bonzini -Signed-off-by: Sasha Levin ---- - arch/x86/kvm/mmu/mmu.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c -index e4813964bfa07a..c03c4341a87fd7 100644 ---- a/arch/x86/kvm/mmu/mmu.c -+++ b/arch/x86/kvm/mmu/mmu.c -@@ -1737,7 +1737,7 @@ static void drop_parent_pte(struct kvm_mmu_page *sp, - mmu_spte_clear_no_track(parent_pte); - } - --static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu, int direct) -+static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu, bool direct) - { - struct kvm_mmu_page *sp; - -@@ -2074,7 +2074,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, - gfn_t gfn, - gva_t gaddr, - unsigned level, -- int direct, -+ bool direct, - unsigned int access) - { - bool direct_mmu = vcpu->arch.mmu->direct_map; --- -2.53.0 - diff --git a/queue-5.15/series b/queue-5.15/series index 0a9cc78a3f..0aa956bebf 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -23,13 +23,6 @@ media-vidtv-fix-null-pointer-dereference-in-vidtv_mux_push_si.patch virtiofs-fix-uaf-on-submount-umount.patch revert-selftest-ptp-update-ptp-selftest-to-exercise-.patch revert-ptp-add-testptp-mask-test.patch -kvm-x86-mmu-use-a-bool-for-direct.patch -kvm-x86-mmu-stop-passing-direct-to-mmu_alloc_root.patch -kvm-x86-mmu-derive-shadow-mmu-page-role-from-parent.patch -kvm-x86-mmu-always-pass-0-for-quadrant-when-gptes-ar.patch -kvm-x86-mmu-pull-call-to-drop_large_spte-into-__link.patch -kvm-x86-fix-shadow-paging-use-after-free-due-to-unex.patch -kvm-x86-fix-shadow-paging-use-after-free-due-to-unex.patch-23529 kvm-x86-mmu-ensure-hugepage-is-in-by-slot-before-che.patch kselftest-arm64-signal-skip-sve-signal-test-if-not-e.patch batman-adv-tp_meter-keep-unacked-list-in-ascending-o.patch