Everything is in place to allow dirty page logging for guest_memfd-only memslots, advertise it to userspace. Signed-off-by: Alexandru Elisei --- arch/arm64/kvm/arm.c | 22 ++++++++++++++++++++++ arch/arm64/kvm/mmu.c | 3 ++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 50adfff75be8..e92e5d7b533a 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -393,6 +393,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_COUNTER_OFFSET: case KVM_CAP_ARM_WRITABLE_IMP_ID_REGS: case KVM_CAP_ARM_SEA_TO_USER: +#ifdef CONFIG_KVM_GUEST_MEMFD + case KVM_CAP_GUEST_MEMFD_MMAP_LOG_DIRTY_PAGES: +#endif r = 1; break; case KVM_CAP_SET_GUEST_DEBUG2: @@ -493,6 +496,25 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) return r; } +#ifdef CONFIG_KVM_GUEST_MEMFD +bool kvm_arch_supports_gmem_mmap_dirty_logging(struct kvm *kvm) +{ + /* + * Protected pKVM VMs don't allow dirty page logging, fail early here + * instead of in kvm_arch_prepare_memory_region(). + * + * KVM_CAP_GUEST_MEMFD_MMAP_LOG_DIRTY_PAGES is not available for a + * protected pKVM VM, and returning false means that + * KVM_SET_USER_MEMORY_REGION2 fails with EINVAL, which is consistent + * with unsupported memslot flags. + */ + if (!is_protected_kvm_enabled()) + return true; + + return kvm_pkvm_ext_allowed(kvm, KVM_CAP_GUEST_MEMFD_MMAP_LOG_DIRTY_PAGES); +} +#endif + long kvm_arch_dev_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index 6c941aaa10c6..f6e6de153ce2 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -1648,7 +1648,8 @@ static int gmem_abort(const struct kvm_s2_fault_desc *s2fd) return ret; } - if (!(s2fd->memslot->flags & KVM_MEM_READONLY)) + if (!(s2fd->memslot->flags & KVM_MEM_READONLY) && + (!kvm_slot_dirty_track_enabled(s2fd->memslot) || write_fault)) prot |= KVM_PGTABLE_PROT_W; if (s2fd->nested) -- 2.43.0