On Thu, 7 May 2026 at 21:22, Ackerley Tng via B4 Relay <[email protected]> wrote: > > From: Sean Christopherson <[email protected]> > > Introduce the basic infrastructure to allow per-VM memory attribute > tracking to be disabled. This will be built-upon in a later patch, where a > module param can disable per-VM memory attribute tracking. > > Split the Kconfig option into a base KVM_MEMORY_ATTRIBUTES and the > existing KVM_VM_MEMORY_ATTRIBUTES. The base option provides the core > plumbing, while the latter enables the full per-VM tracking via an xarray > and the associated ioctls. > > kvm_get_memory_attributes() now performs a static call that either looks up > kvm->mem_attr_array with CONFIG_KVM_VM_MEMORY_ATTRIBUTES is enabled, or > just returns 0 otherwise. The static call can be patched depending on > whether per-VM tracking is enabled by the CONFIG. > > No functional change intended. > > Signed-off-by: Sean Christopherson <[email protected]> > Signed-off-by: Ackerley Tng <[email protected]>
Reviewed-by: Fuad Tabba <[email protected]> Cheers, /fuad > --- > arch/x86/include/asm/kvm_host.h | 2 +- > include/linux/kvm_host.h | 23 ++++++++++++--------- > virt/kvm/Kconfig | 4 ++++ > virt/kvm/kvm_main.c | 44 > ++++++++++++++++++++++++++++++++++++++++- > 4 files changed, 62 insertions(+), 11 deletions(-) > > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h > index 60b997764beef..c9aa50bcdac2d 100644 > --- a/arch/x86/include/asm/kvm_host.h > +++ b/arch/x86/include/asm/kvm_host.h > @@ -2369,7 +2369,7 @@ void kvm_configure_mmu(bool enable_tdp, int > tdp_forced_root_level, > int tdp_max_root_level, int tdp_huge_page_level); > > > -#ifdef CONFIG_KVM_VM_MEMORY_ATTRIBUTES > +#ifdef CONFIG_KVM_MEMORY_ATTRIBUTES > #define kvm_arch_has_private_mem(kvm) ((kvm)->arch.has_private_mem) > #endif > > diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h > index 7d079f9701346..c5ba2cb34e45c 100644 > --- a/include/linux/kvm_host.h > +++ b/include/linux/kvm_host.h > @@ -2528,19 +2528,15 @@ static inline bool kvm_memslot_is_gmem_only(const > struct kvm_memory_slot *slot) > return slot->flags & KVM_MEMSLOT_GMEM_ONLY; > } > > -#ifdef CONFIG_KVM_VM_MEMORY_ATTRIBUTES > +#ifdef CONFIG_KVM_MEMORY_ATTRIBUTES > +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); > + > static inline unsigned long kvm_get_memory_attributes(struct kvm *kvm, gfn_t > gfn) > { > - return xa_to_value(xa_load(&kvm->mem_attr_array, gfn)); > + return static_call(__kvm_get_memory_attributes)(kvm, gfn); > } > > -bool kvm_range_has_memory_attributes(struct kvm *kvm, gfn_t start, gfn_t end, > - unsigned long mask, unsigned long attrs); > -bool kvm_arch_pre_set_memory_attributes(struct kvm *kvm, > - struct kvm_gfn_range *range); > -bool kvm_arch_post_set_memory_attributes(struct kvm *kvm, > - struct kvm_gfn_range *range); > - > static inline bool kvm_mem_is_private(struct kvm *kvm, gfn_t gfn) > { > return kvm_get_memory_attributes(kvm, gfn) & > KVM_MEMORY_ATTRIBUTE_PRIVATE; > @@ -2550,6 +2546,15 @@ static inline bool kvm_mem_is_private(struct kvm *kvm, > gfn_t gfn) > { > return false; > } > +#endif > + > +#ifdef CONFIG_KVM_VM_MEMORY_ATTRIBUTES > +bool kvm_range_has_memory_attributes(struct kvm *kvm, gfn_t start, gfn_t end, > + unsigned long mask, unsigned long attrs); > +bool kvm_arch_pre_set_memory_attributes(struct kvm *kvm, > + struct kvm_gfn_range *range); > +bool kvm_arch_post_set_memory_attributes(struct kvm *kvm, > + struct kvm_gfn_range *range); > #endif /* CONFIG_KVM_VM_MEMORY_ATTRIBUTES */ > > #ifdef CONFIG_KVM_GUEST_MEMFD > diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig > index 5119cb37145fc..3fea89c45cfb4 100644 > --- a/virt/kvm/Kconfig > +++ b/virt/kvm/Kconfig > @@ -100,7 +100,11 @@ config KVM_ELIDE_TLB_FLUSH_IF_YOUNG > config KVM_MMU_LOCKLESS_AGING > bool > > +config KVM_MEMORY_ATTRIBUTES > + bool > + > config KVM_VM_MEMORY_ATTRIBUTES > + select KVM_MEMORY_ATTRIBUTES > bool > > config KVM_GUEST_MEMFD > diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c > index abb9cfa3eb04d..ee26f1d9b5fda 100644 > --- a/virt/kvm/kvm_main.c > +++ b/virt/kvm/kvm_main.c > @@ -101,6 +101,17 @@ EXPORT_SYMBOL_FOR_KVM_INTERNAL(halt_poll_ns_shrink); > static bool __ro_after_init allow_unsafe_mappings; > module_param(allow_unsafe_mappings, bool, 0444); > > +#ifdef CONFIG_KVM_MEMORY_ATTRIBUTES > +#ifdef CONFIG_KVM_VM_MEMORY_ATTRIBUTES > +static bool vm_memory_attributes = true; > +#else > +#define vm_memory_attributes false > +#endif > +DEFINE_STATIC_CALL_RET0(__kvm_get_memory_attributes, > kvm_get_memory_attributes_t); > +EXPORT_SYMBOL_FOR_KVM_INTERNAL(STATIC_CALL_KEY(__kvm_get_memory_attributes)); > +EXPORT_SYMBOL_FOR_KVM_INTERNAL(STATIC_CALL_TRAMP(__kvm_get_memory_attributes)); > +#endif > + > /* > * Ordering of locks: > * > @@ -2418,7 +2429,7 @@ static int kvm_vm_ioctl_clear_dirty_log(struct kvm *kvm, > } > #endif /* CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT */ > > -#ifdef CONFIG_KVM_VM_MEMORY_ATTRIBUTES > +#ifdef CONFIG_KVM_MEMORY_ATTRIBUTES > static u64 kvm_supported_mem_attributes(struct kvm *kvm) > { > #ifdef kvm_arch_has_private_mem > @@ -2429,6 +2440,12 @@ static u64 kvm_supported_mem_attributes(struct kvm > *kvm) > return 0; > } > > +#ifdef CONFIG_KVM_VM_MEMORY_ATTRIBUTES > +static unsigned long kvm_get_vm_memory_attributes(struct kvm *kvm, gfn_t gfn) > +{ > + return xa_to_value(xa_load(&kvm->mem_attr_array, gfn)); > +} > + > /* > * Returns true if _all_ gfns in the range [@start, @end) have attributes > * such that the bits in @mask match @attrs. > @@ -2625,7 +2642,24 @@ static int kvm_vm_ioctl_set_mem_attributes(struct kvm > *kvm, > > return kvm_vm_set_mem_attributes(kvm, start, end, attrs->attributes); > } > +#else /* CONFIG_KVM_VM_MEMORY_ATTRIBUTES */ > +static unsigned long kvm_get_vm_memory_attributes(struct kvm *kvm, gfn_t gfn) > +{ > + BUILD_BUG_ON(1); > +} > #endif /* CONFIG_KVM_VM_MEMORY_ATTRIBUTES */ > +static void kvm_init_memory_attributes(void) > +{ > + if (vm_memory_attributes) > + static_call_update(__kvm_get_memory_attributes, > + kvm_get_vm_memory_attributes); > + else > + static_call_update(__kvm_get_memory_attributes, > + (void *)__static_call_return0); > +} > +#else /* CONFIG_KVM_MEMORY_ATTRIBUTES */ > +static void kvm_init_memory_attributes(void) { } > +#endif /* CONFIG_KVM_MEMORY_ATTRIBUTES */ > > struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn) > { > @@ -4925,6 +4959,9 @@ static int kvm_vm_ioctl_check_extension_generic(struct > kvm *kvm, long arg) > return 1; > #ifdef CONFIG_KVM_VM_MEMORY_ATTRIBUTES > case KVM_CAP_MEMORY_ATTRIBUTES: > + if (!vm_memory_attributes) > + return 0; > + > return kvm_supported_mem_attributes(kvm); > #endif > #ifdef CONFIG_KVM_GUEST_MEMFD > @@ -5331,6 +5368,10 @@ static long kvm_vm_ioctl(struct file *filp, > case KVM_SET_MEMORY_ATTRIBUTES: { > struct kvm_memory_attributes attrs; > > + r = -ENOTTY; > + if (!vm_memory_attributes) > + goto out; > + > r = -EFAULT; > if (copy_from_user(&attrs, argp, sizeof(attrs))) > goto out; > @@ -6527,6 +6568,7 @@ int kvm_init(unsigned vcpu_size, unsigned vcpu_align, > struct module *module) > kvm_preempt_ops.sched_in = kvm_sched_in; > kvm_preempt_ops.sched_out = kvm_sched_out; > > + kvm_init_memory_attributes(); > kvm_init_debug(); > > r = kvm_vfio_ops_init(); > > -- > 2.54.0.563.g4f69b47b94-goog > >
