[PATCH 16/45] KVM: adjust for presence of more than one attribute
From: Paolo Bonzini
Date: Mon Nov 02 2026 - 14:06:43 EST
Remove or adjust code that assumed that the only valid attribute was
KVM_MEMORY_ATTRIBUTE_PRIVATE, in preparation for the introduction of RWX
memory attributes.
In particular, the optimization in kvm_range_has_memory_attributes
simply is not valid if attrs == 0 but some of the attributes are being
ignored. The WARNs in arch/x86/kvm/mmu/mmu.c are just a duplicate of
checking kvm_supported_mem_attributes() during the ioctl, so drop it.
Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
Link: https://patch.msgid.link/20260918135030.171564-13-pbonzini@xxxxxxxxxx
Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
---
arch/x86/kvm/mmu/mmu.c | 9 +--------
virt/kvm/kvm_main.c | 10 +++++++---
2 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index 3755393de4ca..b89517794034 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -8226,9 +8226,6 @@ bool kvm_arch_pre_set_vm_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;
@@ -8304,11 +8301,7 @@ bool kvm_arch_post_set_vm_memory_attributes(struct kvm *kvm,
* 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.
*/
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 2fd595a901bd..17341c689d11 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2490,10 +2490,12 @@ bool kvm_range_has_vm_memory_attributes(struct kvm *kvm, gfn_t start, gfn_t end,
unsigned long mask, unsigned long attrs)
{
XA_STATE(xas, &kvm->mem_attr_array, start);
+ unsigned long supported_attrs;
unsigned long index;
void *entry;
- mask &= kvm_supported_vm_mem_attributes(kvm);
+ supported_attrs = kvm_supported_vm_mem_attributes(kvm);
+ mask &= supported_attrs;
if (attrs & ~mask)
return false;
@@ -2522,8 +2524,10 @@ bool kvm_range_has_vm_memory_attributes(struct kvm *kvm, gfn_t start, gfn_t end,
*/
for (index = start; index < end; index++) {
do {
- entry = attrs ? xas_next(&xas) :
- xas_next_entry(&xas, end - 1);
+ if (!attrs && mask == supported_attrs)
+ entry = xas_next_entry(&xas, end - 1);
+ else
+ entry = xas_next(&xas);
} while (xas_retry(&xas, entry));
if (!entry)
--
2.52.0