Live migration of confidential guests needs the help of KVM at least for TDX. Add KVM_CAP_LIVE_MIGRATION for when hardware specific live migration functions must be used. Add KVM_MIGRATE_CMD to configure the hardware for live migration. Assisted-by: Claude-Code:claude-opus-5 checkpatch [ used AI to review and simplify the code ] Signed-off-by: Tony Lindgren --- arch/x86/include/asm/kvm-x86-ops.h | 2 ++ arch/x86/include/asm/kvm_host.h | 2 ++ arch/x86/kvm/x86.c | 25 +++++++++++++++++++++++++ include/uapi/linux/kvm.h | 22 ++++++++++++++++++++++ 4 files changed, 51 insertions(+) diff --git a/arch/x86/include/asm/kvm-x86-ops.h b/arch/x86/include/asm/kvm-x86-ops.h index 83dc5086138b3..ac080b556b0c8 100644 --- a/arch/x86/include/asm/kvm-x86-ops.h +++ b/arch/x86/include/asm/kvm-x86-ops.h @@ -148,6 +148,8 @@ KVM_X86_OP_OPTIONAL(alloc_apic_backing_page) KVM_X86_OP_OPTIONAL_RET0(gmem_prepare) KVM_X86_OP_OPTIONAL_RET0(gmem_max_mapping_level) KVM_X86_OP_OPTIONAL(gmem_invalidate) +KVM_X86_OP_OPTIONAL_RET0(cap_live_migration) +KVM_X86_OP_OPTIONAL(migrate_cmd) #endif #undef KVM_X86_OP diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 5f6c1ce9673b7..d9291a8a97bb1 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -2010,6 +2010,8 @@ struct kvm_x86_ops { int (*gmem_prepare)(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order); void (*gmem_invalidate)(kvm_pfn_t start, kvm_pfn_t end); int (*gmem_max_mapping_level)(struct kvm *kvm, kvm_pfn_t pfn, bool is_private); + bool (*cap_live_migration)(struct kvm *kvm); + int (*migrate_cmd)(struct kvm *kvm, struct kvm_migrate_cmd *cmd); }; struct kvm_x86_nested_ops { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index afcac1042947a..7064fd709e56d 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4973,6 +4973,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_READONLY_MEM: r = kvm ? kvm_arch_has_readonly_mem(kvm) : 1; break; + case KVM_CAP_LIVE_MIGRATION: + r = kvm ? kvm_x86_call(cap_live_migration)(kvm) : 0; + break; default: break; } @@ -7614,6 +7617,28 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) r = kvm_vm_ioctl_set_msr_filter(kvm, &filter); break; } + case KVM_MIGRATE_CMD: { + struct kvm_migrate_cmd cmd; + + if (!kvm_x86_ops.migrate_cmd || + !kvm_x86_call(cap_live_migration)(kvm)) + return -ENOTTY; + + if (copy_from_user(&cmd, argp, sizeof(cmd))) + return -EFAULT; + + if (cmd.reserved || cmd.buf.reserved) + return -EINVAL; + + r = kvm_x86_call(migrate_cmd)(kvm, &cmd); + if (r > 0) + r = -EIO; + + /* Copy back also on an error to report a partially done command */ + if (copy_to_user(argp, &cmd, sizeof(cmd))) + return -EFAULT; + break; + } default: r = -ENOTTY; } diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 419011097fa8e..e5b227d3a8e40 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -997,6 +997,7 @@ struct kvm_enable_cap { #define KVM_CAP_S390_KEYOP 247 #define KVM_CAP_S390_VSIE_ESAMODE 248 #define KVM_CAP_S390_HPAGE_2G 249 +#define KVM_CAP_LIVE_MIGRATION 250 struct kvm_irq_routing_irqchip { __u32 irqchip; @@ -1350,6 +1351,8 @@ struct kvm_s390_keyop { #define KVM_GET_DEVICE_ATTR _IOW(KVMIO, 0xe2, struct kvm_device_attr) #define KVM_HAS_DEVICE_ATTR _IOW(KVMIO, 0xe3, struct kvm_device_attr) +#define KVM_MIGRATE_CMD _IOWR(KVMIO, 0xe4, struct kvm_migrate_cmd) + /* * ioctls for vcpu fds */ @@ -1670,4 +1673,23 @@ struct kvm_pre_fault_memory { __u64 padding[5]; }; +#define KVM_MIGRATE_SETUP 0 +#define KVM_MIGRATE_ITERATION 1 +#define KVM_MIGRATE_STOP_AND_COPY 2 +#define KVM_MIGRATE_ABORT 3 +#define KVM_MIGRATE_END 4 + +struct kvm_transfer_buffer { + __u64 address; + __u32 size; + __u32 reserved; +}; + +struct kvm_migrate_cmd { + __u16 command; + __u16 flags; + __u32 reserved; + struct kvm_transfer_buffer buf; +}; + #endif /* __LINUX_KVM_H */ -- 2.43.0