[PATCH 06/24] KVM: x86: Avoid warning when installing non-private memory attributes
From: Paolo Bonzini
Date: Thu Jul 16 2026 - 14:24:11 EST
From: Nicolas Saenz Julienne <nsaenz@xxxxxxxxxx>
In preparation to introducing RWX memory attributes. Make sure
user-space is attempting to install a memory attribute with
KVM_MEMORY_ATTRIBUTE_PRIVATE before throwing a warning on systems with
no private memory support.
The WARN is really a duplicate of the kvm_supported_mem_attributes()
test in kvm_vm_ioctl_set_mem_attributes(), but then all of them should
be redundant... Keep it as a special check for the private-memory
attribute, to avoid that kvm_mmu_page_fault() sets PFERR_PRIVATE_ACCESS;
that bit would send KVM down kvm_mmu_faultin_pfn_gmem(), which is such
a wrong path that it's worth catching it early.
Signed-off-by: Nicolas Saenz Julienne <nsaenz@xxxxxxxxxx>
Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
---
arch/x86/kvm/mmu/mmu.c | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index 424f4e113682..055e0b45a8ee 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -8078,9 +8078,15 @@ static void hugepage_set_mixed(struct kvm_memory_slot *slot, gfn_t gfn,
bool kvm_arch_pre_set_memory_attributes(struct kvm *kvm,
struct kvm_gfn_range *range)
{
+ unsigned long attrs = range->arg.attributes;
struct kvm_memory_slot *slot = range->slot;
int level;
+ if (!kvm_arch_has_private_mem(kvm)) {
+ WARN_ON(attrs & KVM_MEMORY_ATTRIBUTE_PRIVATE);
+ attrs &= ~KVM_MEMORY_ATTRIBUTE_PRIVATE;
+ }
+
/*
* Zap SPTEs even if the slot can't be mapped PRIVATE. KVM x86 only
* supports KVM_MEMORY_ATTRIBUTE_PRIVATE, and so it *seems* like KVM
@@ -8092,9 +8098,6 @@ bool kvm_arch_pre_set_memory_attributes(struct kvm *kvm,
* Zapping SPTEs in this case ensures KVM will reassess whether or not
* a hugepage can be used for affected ranges.
*/
- if (WARN_ON_ONCE(!kvm_arch_has_private_mem(kvm)))
- return false;
-
if (WARN_ON_ONCE(range->end <= range->start))
return false;
@@ -8165,16 +8168,17 @@ bool kvm_arch_post_set_memory_attributes(struct kvm *kvm,
lockdep_assert_held_write(&kvm->mmu_lock);
lockdep_assert_held(&kvm->slots_lock);
+ if (!kvm_arch_has_private_mem(kvm)) {
+ WARN_ON(attrs & KVM_MEMORY_ATTRIBUTE_PRIVATE);
+ attrs &= ~KVM_MEMORY_ATTRIBUTE_PRIVATE;
+ }
+
/*
* Calculate which ranges can be mapped with hugepages even if the slot
* can't map memory PRIVATE. KVM mustn't create a SHARED hugepage over
* a range that has PRIVATE GFNs, and conversely converting a range to
* SHARED may now allow hugepages.
- */
- if (WARN_ON_ONCE(!kvm_arch_has_private_mem(kvm)))
- return false;
-
- /*
+ *
* The sequence matters here: upper levels consume the result of lower
* level's scanning.
*/
--
2.52.0