Re: [PATCH 07/13] KVM: x86/mmu: Track PRIVATE impact on hugepage mappings for all memslots

Binbin Wu
2023-09-27T06:03:25Z

On 9/22/2023 4:33 AM, Sean Christopherson wrote:
> Track the effects of private attributes on potential hugepage mappings if
> the VM supports private memory, i.e. even if the target memslot can only
> ever be mapped shared. If userspace configures a chunk of memory as
> private, KVM must not allow that memory to be mapped shared regardless of
> whether or not the *current* memslot can be mapped private. E.g. if the
> guest accesses a private range using a shared memslot, then KVM must exit
> to userspace.
How does usersapce handle this case?
IIRC, in gmem v12 patch set, it says a memslot can not be convert to
private from shared.
So, userspace should delete the old memslot and and a new one?

> Fixes: 5bb0b4e162d1 ("KVM: x86: Disallow hugepages when memory attributes are mixed")
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
> arch/x86/kvm/mmu/mmu.c | 10 ++++++----
> 1 file changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
> index 269d4dc47c98..148931cf9dba 100644
> --- a/arch/x86/kvm/mmu/mmu.c
> +++ b/arch/x86/kvm/mmu/mmu.c
> @@ -7314,10 +7314,12 @@ bool kvm_arch_post_set_memory_attributes(struct kvm *kvm,
> lockdep_assert_held(&kvm->slots_lock);
>
> /*
> - * KVM x86 currently only supports KVM_MEMORY_ATTRIBUTE_PRIVATE, skip
> - * the slot if the slot will never consume the PRIVATE attribute.
> + * 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 (!kvm_slot_can_be_private(slot))
> + if (WARN_ON_ONCE(!kvm_arch_has_private_mem(kvm)))
> return false;
>
> /*
> @@ -7372,7 +7374,7 @@ void kvm_mmu_init_memslot_memory_attributes(struct kvm *kvm,
> {
> int level;
>
> - if (!kvm_slot_can_be_private(slot))
> + if (!kvm_arch_has_private_mem(kvm))
> return;
>
> for (level = PG_LEVEL_2M; level <= KVM_MAX_HUGEPAGE_LEVEL; level++) {