[PATCH RFC v4 15/44] KVM: Add CAP to enumerate supported SET_MEMORY_ATTRIBUTES2 flags

From: Ackerley Tng

Date: Thu Mar 26 2026 - 18:32:41 EST


Add CAP to enumerate supported SET_MEMORY_ATTRIBUTES2 flags, so userspace
can find out which flags are supported when sending the
KVM_SET_MEMORY_ATTRIBUTES2 ioctl to a guest_memfd.

These flags are only supported by guest_memfd, hence, if
vm_memory_attributes is enabled, return 0 - no flags are supported when
KVM_SET_MEMORY_ATTRIBUTES2 is sent to a VM fd.

Signed-off-by: Ackerley Tng <ackerleytng@xxxxxxxxxx>
---
Documentation/virt/kvm/api.rst | 3 +++
include/linux/kvm_host.h | 12 ++++++++++++
include/uapi/linux/kvm.h | 1 +
virt/kvm/kvm_main.c | 5 +++++
4 files changed, 21 insertions(+)

diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index 90587a9c09d3f..73101d6e649b7 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -6680,6 +6680,9 @@ guarantees are made on offset ranges that do not have memory allocated
and range [0x0000, 0x3000) was set to shared, the content mode would
apply to only to offset ranges [0x0000, 0x1000) and [0x2000, 0x3000).

+The supported content modes can be queried using
+``KVM_CAP_MEMORY_ATTRIBUTES2_FLAGS``.
+
See also: :ref: `KVM_SET_MEMORY_ATTRIBUTES`.

.. _kvm_run:
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 4ba3c4b303f4a..d671c9795dfce 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -2536,6 +2536,18 @@ static inline u64 kvm_supported_mem_attributes(struct kvm *kvm)
return 0;
}

+static inline u64 kvm_supported_set_mem_attributes2_flags(struct kvm *kvm)
+{
+ if (!IS_ENABLED(CONFIG_KVM_GUEST_MEMFD))
+ return 0;
+
+ if (!kvm)
+ return KVM_SET_MEMORY_ATTRIBUTES2_ZERO |
+ KVM_SET_MEMORY_ATTRIBUTES2_PRESERVE;
+
+ return kvm_arch_gmem_supported_content_modes(kvm);
+}
+
typedef unsigned long (kvm_get_memory_attributes_t)(struct kvm *kvm, gfn_t gfn);
DECLARE_STATIC_CALL(__kvm_get_memory_attributes, kvm_get_memory_attributes_t);

diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 0fc9ad4ea0d93..4d1e09d022c48 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -991,6 +991,7 @@ struct kvm_enable_cap {
#define KVM_CAP_S390_KEYOP 247
#define KVM_CAP_MEMORY_ATTRIBUTES2 248
#define KVM_CAP_GUEST_MEMFD_MEMORY_ATTRIBUTES 249
+#define KVM_CAP_MEMORY_ATTRIBUTES2_FLAGS 250

struct kvm_irq_routing_irqchip {
__u32 irqchip;
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 85c14197587d4..6607127eaaeed 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -4980,6 +4980,11 @@ static int kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg)
return 0;

return kvm_supported_mem_attributes(kvm);
+ case KVM_CAP_MEMORY_ATTRIBUTES2_FLAGS:
+ if (vm_memory_attributes)
+ return 0;
+
+ return kvm_supported_set_mem_attributes2_flags(kvm);
#endif
default:
break;

--
2.53.0.1018.g2bb0e51243-goog