From: Nicolas Saenz Julienne 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 Signed-off-by: Paolo Bonzini --- 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