[PATCH 2/8] KVM: arm64: add page tracking device as a capability

Lilit Janpoladyan
2024-09-18T15:28:19Z

Add new capability KVM_CAP_ARM_PAGE_TRACKING_DEVICE to use page tracking
device for dirty logging. The capability can be used only if platform
supports such a device i.e. when KVM_CAP_ARM_PAGE_TRACKING_DEVICE
extension is supported. Until there is dirty ring support, make new
capability incompatible with the use of dirty ring.

When page tracking device is in use, instead of logging dirty pages on
faults KVM will collect a list of dirty pages from the device when
userspace reads dirty bitmap.

Signed-off-by: Lilit Janpoladyan <lilitj@amazon.com>
---
Documentation/virt/kvm/api.rst | 17 +++++++++++++++++
arch/arm64/include/asm/kvm_host.h | 2 ++
arch/arm64/kvm/arm.c | 17 +++++++++++++++++
include/uapi/linux/kvm.h | 1 +
4 files changed, 37 insertions(+)

diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index b3be87489108..989d5dd886fb 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -8950,6 +8950,23 @@ Do not use KVM_X86_SW_PROTECTED_VM for "real" VMs, and especially not in
production. The behavior and effective ABI for software-protected VMs is
unstable.

+8.42 KVM_CAP_ARM_PAGE_TRACKING_DEVICE
+_____________________________________
+
+:Capability: KVM_CAP_ARM_PAGE_TRACKING_DEVICE
+:Architecture: arm64
+:Type: vm
+:Parameters: arg[0] whether feature should be enabled or not
+:Returns 0 on success, -errno on failure
+
+This capability enables or disables hardware assistance for dirty page logging.
+
+In case page tracking device is available (i.e. if the host supports the
+KVM_CAP_ARM_PAGE_TRACKING_DEVICE extension), the device can be used to accelerate
+dirty logging. This capability turns the acceleration on and off.
+
+Not compatible with KVM_CAP_DIRTY_LOG_RING/KVM_CAP_DIRTY_LOG_RING_ACQ_REL.
+
9. Known KVM API problems
=========================

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index a33f5996ca9f..5b5e3647fbda 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -326,6 +326,8 @@ struct kvm_arch {
#define KVM_ARCH_FLAG_ID_REGS_INITIALIZED 7
/* Fine-Grained UNDEF initialised */
#define KVM_ARCH_FLAG_FGU_INITIALIZED 8
+ /* Page tracking device enabled */
+#define KVM_ARCH_FLAG_PAGE_TRACKING_DEVICE_ENABLED 9
unsigned long flags;

/* VM-wide vCPU feature set */
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 9bef7638342e..aea56df8ac04 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -40,6 +40,7 @@
#include <asm/kvm_nested.h>
#include <asm/kvm_pkvm.h>
#include <asm/kvm_ptrauth.h>
+#include <asm/page_tracking.h>
#include <asm/sections.h>

#include <kvm/arm_hypercalls.h>
@@ -149,6 +150,19 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
}
mutex_unlock(&kvm->slots_lock);
break;
+ case KVM_CAP_ARM_PAGE_TRACKING_DEVICE:
+ if (page_tracking_device_registered() &&
+ !kvm->dirty_ring_size /* Does not support dirty ring yet */) {
+
+ r = 0;
+ if (cap->args[0])
+ set_bit(KVM_ARCH_FLAG_PAGE_TRACKING_DEVICE_ENABLED,
+ &kvm->arch.flags);
+ else
+ clear_bit(KVM_ARCH_FLAG_PAGE_TRACKING_DEVICE_ENABLED,
+ &kvm->arch.flags);
+ }
+ break;
default:
break;
}
@@ -416,6 +430,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES:
r = BIT(0);
break;
+ case KVM_CAP_ARM_PAGE_TRACKING_DEVICE:
+ r = page_tracking_device_registered();
+ break;
default:
r = 0;
}
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 637efc055145..552ebede3f9d 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -933,6 +933,7 @@ struct kvm_enable_cap {
#define KVM_CAP_PRE_FAULT_MEMORY 236
#define KVM_CAP_X86_APIC_BUS_CYCLES_NS 237
#define KVM_CAP_X86_GUEST_MODE 238
+#define KVM_CAP_ARM_PAGE_TRACKING_DEVICE 239

struct kvm_irq_routing_irqchip {
__u32 irqchip;
--
2.40.1