* [RFC PATCH v2 1/4] Documentation: KVM: Add live migration API for confidential guests
2026-08-31 7:13 [RFC PATCH v2 0/4] Add KVM API for confidential guest live migration Tony Lindgren
@ 2026-08-31 7:13 ` Tony Lindgren
2026-08-31 7:20 ` sashiko-bot
2026-08-31 7:13 ` [RFC PATCH v2 2/4] KVM: x86: Add optional KVM_CAP_LIVE_MIGRATION and KVM_MIGRATE_CMD Tony Lindgren
` (2 subsequent siblings)
3 siblings, 1 reply; 9+ messages in thread
From: Tony Lindgren @ 2026-08-31 7:13 UTC (permalink / raw)
To: Paolo Bonzini, Sean Christopherson
Cc: Peter Xu, Artem Bityutskiy, Fabiano Rosas, Jon Grimm,
Pankaj Gupta, Tom Lendacky, Marc Zyngier, Oliver Upton,
Steven Price, Anup Patel, Samuel Ortiz,
Jakub Růžička, Jörg Rödel ,
Vishal Annapurve, Elena Reshetova, Kai Huang, Kishen Maloor,
Mika Westerberg, Peter Fang, Rick Edgecombe, Xiaoyao Li, Xu Yilun,
kvm
For CoCo VMs, the guest memory and vCPU states are not accessible to the
userspace or KVM for live migration. The memory and vCPU states need to be
extracted into encrypted blobs on the source, and decrypted on the
destination. Before live migration, an encryption key needs to be
negotiated between the source and destination.
KVM help is needed to talk to the layer exporting and importing the
encrypted state. Document the KVM live migration API for confidential
guests.
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Tony Lindgren <tony.lindgren@linux.intel.com>
---
Documentation/virt/kvm/api.rst | 205 +++++++++++++++++++++++++++++++++
1 file changed, 205 insertions(+)
diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index a5f9ee92f43e8..9d546d288af5f 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -6566,6 +6566,200 @@ KVM_S390_KEYOP_SSKE
Sets the storage key for the guest address ``guest_addr`` to the key
specified in ``key``, returning the previous value in ``key``.
+.. _KVM_MIGRATE_CMD:
+
+4.145 KVM_MIGRATE_CMD
+---------------------
+
+:Capability: KVM_CAP_LIVE_MIGRATION
+:Architectures: x86
+:Type: vm ioctl
+:Parameters: struct kvm_migrate_cmd (in/out)
+:Returns: 0 on success, < 0 on error
+
+Allows userspace to send live migration related commands to KVM for vendor
+specific handling.
+
+For confidential computing, live migration related commands may be needed.
+The commands typically use encrypted data that needs to be passed between the
+source and destination hosts. The hosts may also require specific coordination
+steps during migration that must be triggered at precise points in the
+migration process.
+
+The vendor specific implementation handles locking and checks the valid flags
+bits. If KVM_CAP_LIVE_MIGRATION is not available for the VM, -ENOTTY is
+returned.
+
+The KVM_MIGRATE_CMD subcommand passed in struct kvm_migrate_cmd is one of::
+
+ #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
+
+The kvm_transfer_buffer is::
+
+ /**
+ * @address: Userspace buffer address
+ * @size: Size of the userspace buffer
+ * @reserved: Reserved for future use
+ */
+ struct kvm_transfer_buffer {
+ __u64 address;
+ __u32 size;
+ __u32 reserved;
+ };
+
+The kvm_migrate_cmd is::
+
+ /**
+ * @command: One of the defined KVM_MIGRATE commands
+ * @flags: Hardware specific flags
+ * @reserved: Reserved for future use
+ * @buf: Userspace buffer for hardware specific data
+ */
+ struct kvm_migrate_cmd {
+ __u16 command;
+ __u16 flags;
+ __u32 reserved;
+ struct kvm_transfer_buffer buf;
+ };
+
+.. _KVM_EXPORT_MEMORY:
+
+4.146 KVM_EXPORT_MEMORY
+-----------------------
+
+:Capability: KVM_CAP_LIVE_MIGRATION
+:Architectures: x86
+:Type: vm ioctl
+:Parameters: struct kvm_memory_transfer (in/out)
+:Returns: 0 on success, < 0 on error
+
+Allows userspace to request the host to export an array of memory pages to a
+userspace buffer.
+
+The private memory may not be accessible to KVM because of encryption. For
+confidential computing, the guest memory is encrypted and only accessible to
+the guest.
+
+If KVM_CAP_LIVE_MIGRATION is not available for the VM, -ENOTTY is returned.
+
+The vendor specific ID is used at least for TDX for the migration thread
+index.
+
+The kvm_memory_transfer is::
+
+ /**
+ * @gfns: Userspace address of an array of nr_gfns __u64 GFNs to export
+ * @nr_gfns: Number of GFNs in the @gfns array
+ * @id: Optional vendor specific transfer ID
+ * @flags: Vendor specific flags
+ * @reserved: Reserved for future use
+ * @buf: Userspace buffer to export memory to
+ */
+ struct kvm_memory_transfer {
+ __u64 gfns;
+ __u32 nr_gfns;
+ __u16 id;
+ __u16 flags;
+ __u64 reserved;
+ struct kvm_transfer_buffer buf;
+ };
+
+The transfer buffer size is vendor specific.
+
+For the transfer buffer, seeo :ref:`KVM_MIGRATE_CMD <KVM_MIGRATE_CMD>`.
+
+For memory import, see also :ref:`KVM_IMPORT_MEMORY <KVM_IMPORT_MEMORY>`.
+
+
+.. _KVM_IMPORT_MEMORY:
+
+4.147 KVM_IMPORT_MEMORY
+-----------------------
+
+:Capability: KVM_CAP_LIVE_MIGRATION
+:Architectures: x86
+:Type: vm ioctl
+:Parameters: struct kvm_memory_transfer (in/out)
+:Returns: 0 on success, < 0 on error
+
+Allows userspace to request the host to import an array of memory pages from a
+userspace buffer.
+
+The private memory may not be accessible to KVM because of encryption. For
+confidential computing, the guest memory is encrypted and only accessible to
+the guest.
+
+If KVM_CAP_LIVE_MIGRATION is not available for the VM, -ENOTTY is returned.
+
+The vendor specific ID is used at least for TDX for the migration thread
+index.
+
+The transfer buffer size is vendor specific.
+
+For kvm_memory_transfer, see :ref:`KVM_EXPORT_MEMORY <KVM_EXPORT_MEMORY>`.
+
+For the transfer buffer, seeo :ref:`KVM_MIGRATE_CMD <KVM_MIGRATE_CMD>`.
+
+.. _KVM_EXPORT_VCPU:
+
+4.149 KVM_EXPORT_VCPU
+---------------------
+:Capability: KVM_CAP_LIVE_MIGRATION
+:Architectures: arm64, x86
+:Type: vcpu ioctl
+:Parameters: struct kvm_vcpu_transfer (in/out)
+:Returns: 0 on success, < 0 on error
+
+Allows userspace to request the host to export a VCPU state to a userspace
+buffer.
+
+The VCPU state may not be directly accessible to KVM because of encryption. For
+confidential computing, the VCPU state is encrypted and only accessible to the
+guest.
+
+The vcpu_transfer is::
+
+ /**
+ * @flags: Hardware specific flags
+ * @reserved: Reserved for future use
+ * @buf: Userspace buffer to export VCPU state to
+ */
+ struct kvm_vcpu_transfer {
+ __u32 flags;
+ __u32 reserved;
+ struct kvm_transfer_buffer buf;
+ };
+
+For the transfer buffer, see :ref:`KVM_MIGRATE_CMD <KVM_MIGRATE_CMD>`.
+
+For vCPU import, see also :ref:`KVM_IMPORT_VCPU <KVM_IMPORT_VCPU>`.
+
+.. _KVM_IMPORT_VCPU:
+
+4.148 KVM_IMPORT_VCPU
+---------------------
+
+:Capability: KVM_CAP_LIVE_MIGRATION
+:Architectures: arm64, x86
+:Type: vcpu ioctl
+:Parameters: struct kvm_vcpu_transfer (in/out)
+:Returns: 0 on success, < 0 on error
+
+Allows userspace to request the host to import a VCPU state from a userspace
+buffer.
+
+The VCPU state may not be directly accessible to KVM because of encryption. For
+confidential computing, the VCPU state is encrypted and only accessible to the
+guest.
+
+For vcpu_transfer and vCPU import, see :ref:`KVM_IMPORT_VCPU <KVM_IMPORT_VCPU>`.
+
+For the transfer buffer, see also :ref:`KVM_MIGRATE_CMD <KVM_MIGRATE_CMD>`.
+
.. _kvm_run:
5. The kvm_run structure
@@ -9493,6 +9687,17 @@ take care to differentiate between these cases.
The presence of this capability indicates that the nested KVM guest can
start in ESA mode.
+8.48 KVM_CAP_LIVE_MIGRATION
+---------------------------
+
+:Architectures: x86
+:Target: VM
+:Parameters: None
+
+Indicates that the VM needs to use KVM calls for live migration, and that the
+KVM_MIGRATE_CMD ioctl and the KVM_EXPORT_MEMORY, KVM_IMPORT_MEMORY,
+KVM_EXPORT_VCPU and KVM_IMPORT_VCPU ioctls are available.
+
9. Known KVM API problems
=========================
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [RFC PATCH v2 1/4] Documentation: KVM: Add live migration API for confidential guests
2026-08-31 7:13 ` [RFC PATCH v2 1/4] Documentation: KVM: Add live migration API for confidential guests Tony Lindgren
@ 2026-08-31 7:20 ` sashiko-bot
0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-08-31 7:20 UTC (permalink / raw)
To: Tony Lindgren; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] The newly added documentation for the KVM live migration API contains architectural contradictions, backwards numbering, self-referencing links, and typographical errors.
--
commit 3a6c0c9c47ef3277e964b009e8dd06e7aeab932d
Author: Tony Lindgren <tony.lindgren@linux.intel.com>
Documentation: KVM: Add live migration API for confidential guests
For CoCo VMs, the guest memory and vCPU states are not accessible to the
userspace or KVM for live migration. The memory and vCPU states need to be
extracted into encrypted blobs on the source, and decrypted on the
destination. Before live migration, an encryption key needs to be
negotiated between the source and destination.
> diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> index a5f9ee92f43e8..9d546d288af5f 100644
> --- a/Documentation/virt/kvm/api.rst
> +++ b/Documentation/virt/kvm/api.rst
[ ... ]
> +The transfer buffer size is vendor specific.
> +
> +For the transfer buffer, seeo :ref:`KVM_MIGRATE_CMD <KVM_MIGRATE_CMD>`.
[Severity: Low]
Is this "seeo" a typo for "see"?
> +
> +For memory import, see also :ref:`KVM_IMPORT_MEMORY <KVM_IMPORT_MEMORY>`.
> +
> +
> +.. _KVM_IMPORT_MEMORY:
> +
> +4.147 KVM_IMPORT_MEMORY
> +-----------------------
[ ... ]
> +The transfer buffer size is vendor specific.
> +
> +For kvm_memory_transfer, see :ref:`KVM_EXPORT_MEMORY <KVM_EXPORT_MEMORY>`.
> +
> +For the transfer buffer, seeo :ref:`KVM_MIGRATE_CMD <KVM_MIGRATE_CMD>`.
[Severity: Low]
Is there another "seeo" typo here?
> +
> +.. _KVM_EXPORT_VCPU:
> +
> +4.149 KVM_EXPORT_VCPU
> +---------------------
> +:Capability: KVM_CAP_LIVE_MIGRATION
> +:Architectures: arm64, x86
[Severity: Low]
Is it intentional that KVM_EXPORT_VCPU is numbered 4.149 before
KVM_IMPORT_VCPU which is numbered 4.148?
Also, KVM_EXPORT_VCPU lists arm64 as a supported architecture, but relies on
KVM_CAP_LIVE_MIGRATION which is documented as x86 only below. Should arm64 be
removed here, or added to the capability documentation?
> +:Type: vcpu ioctl
> +:Parameters: struct kvm_vcpu_transfer (in/out)
> +:Returns: 0 on success, < 0 on error
[ ... ]
> +.. _KVM_IMPORT_VCPU:
> +
> +4.148 KVM_IMPORT_VCPU
> +---------------------
> +
> +:Capability: KVM_CAP_LIVE_MIGRATION
> +:Architectures: arm64, x86
> +:Type: vcpu ioctl
> +:Parameters: struct kvm_vcpu_transfer (in/out)
> +:Returns: 0 on success, < 0 on error
> +
> +Allows userspace to request the host to import a VCPU state from a userspace
> +buffer.
> +
> +The VCPU state may not be directly accessible to KVM because of encryption. For
> +confidential computing, the VCPU state is encrypted and only accessible to the
> +guest.
> +
> +For vcpu_transfer and vCPU import, see :ref:`KVM_IMPORT_VCPU <KVM_IMPORT_VCPU>`.
[Severity: Low]
Does this circular reference point to itself? Should this point to
KVM_EXPORT_VCPU instead to help the reader find the struct kvm_vcpu_transfer
definition?
> +
> +For the transfer buffer, see also :ref:`KVM_MIGRATE_CMD <KVM_MIGRATE_CMD>`.
> +
> .. _kvm_run:
>
> 5. The kvm_run structure
> @@ -9493,6 +9687,17 @@ take care to differentiate between these cases.
> The presence of this capability indicates that the nested KVM guest can
> start in ESA mode.
>
> +8.48 KVM_CAP_LIVE_MIGRATION
> +---------------------------
> +
> +:Architectures: x86
> +:Target: VM
> +:Parameters: None
[Severity: Low]
The KVM_CAP_LIVE_MIGRATION capability is documented here as x86 only, but
KVM_EXPORT_VCPU and KVM_IMPORT_VCPU state they are for arm64 and x86. Is
this capability intended to support arm64 as well?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260831071304.762939-1-tony.lindgren@linux.intel.com?part=1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [RFC PATCH v2 2/4] KVM: x86: Add optional KVM_CAP_LIVE_MIGRATION and KVM_MIGRATE_CMD
2026-08-31 7:13 [RFC PATCH v2 0/4] Add KVM API for confidential guest live migration Tony Lindgren
2026-08-31 7:13 ` [RFC PATCH v2 1/4] Documentation: KVM: Add live migration API for confidential guests Tony Lindgren
@ 2026-08-31 7:13 ` Tony Lindgren
2026-08-31 7:23 ` sashiko-bot
2026-08-31 7:13 ` [RFC PATCH v2 3/4] KVM: x86: Add optional KVM_EXPORT_MEMORY and KVM_IMPORT_MEMORY Tony Lindgren
2026-08-31 7:13 ` [RFC PATCH v2 4/4] KVM: x86: Add optional KVM_EXPORT_VCPU and KVM_IMPORT_VCPU Tony Lindgren
3 siblings, 1 reply; 9+ messages in thread
From: Tony Lindgren @ 2026-08-31 7:13 UTC (permalink / raw)
To: Paolo Bonzini, Sean Christopherson
Cc: Peter Xu, Artem Bityutskiy, Fabiano Rosas, Jon Grimm,
Pankaj Gupta, Tom Lendacky, Marc Zyngier, Oliver Upton,
Steven Price, Anup Patel, Samuel Ortiz,
Jakub Růžička, Jörg Rödel ,
Vishal Annapurve, Elena Reshetova, Kai Huang, Kishen Maloor,
Mika Westerberg, Peter Fang, Rick Edgecombe, Xiaoyao Li, Xu Yilun,
kvm
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 <tony.lindgren@linux.intel.com>
---
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
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [RFC PATCH v2 2/4] KVM: x86: Add optional KVM_CAP_LIVE_MIGRATION and KVM_MIGRATE_CMD
2026-08-31 7:13 ` [RFC PATCH v2 2/4] KVM: x86: Add optional KVM_CAP_LIVE_MIGRATION and KVM_MIGRATE_CMD Tony Lindgren
@ 2026-08-31 7:23 ` sashiko-bot
0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-08-31 7:23 UTC (permalink / raw)
To: Tony Lindgren; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] The 'flags' field in the new 'struct kvm_migrate_cmd' UAPI is not validated to be zero.
--
commit b50bc10fe65ad9a54c9b979c445505e5baf76592
Author: Tony Lindgren <tony.lindgren@linux.intel.com>
KVM: x86: Add optional KVM_CAP_LIVE_MIGRATION and KVM_MIGRATE_CMD
This patch introduces the KVM_CAP_LIVE_MIGRATION capability and the
KVM_MIGRATE_CMD ioctl. These additions allow KVM to configure hardware-specific
live migration functions, which is necessary for confidential guests like TDX.
> 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
[ ... ]
> @@ -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;
[Severity: High]
Does this code also need to validate that the new flags field is zero?
If uninitialized memory or garbage is passed by userspace in cmd.flags, it
will currently be silently ignored. When a future kernel introduces a new
flag, old userspace applications passing uninitialized flags will inadvertently
enable it, which could permanently break backwards compatibility.
> +
> + 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;
> + }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260831071304.762939-1-tony.lindgren@linux.intel.com?part=2
^ permalink raw reply [flat|nested] 9+ messages in thread
* [RFC PATCH v2 3/4] KVM: x86: Add optional KVM_EXPORT_MEMORY and KVM_IMPORT_MEMORY
2026-08-31 7:13 [RFC PATCH v2 0/4] Add KVM API for confidential guest live migration Tony Lindgren
2026-08-31 7:13 ` [RFC PATCH v2 1/4] Documentation: KVM: Add live migration API for confidential guests Tony Lindgren
2026-08-31 7:13 ` [RFC PATCH v2 2/4] KVM: x86: Add optional KVM_CAP_LIVE_MIGRATION and KVM_MIGRATE_CMD Tony Lindgren
@ 2026-08-31 7:13 ` Tony Lindgren
2026-08-31 7:23 ` sashiko-bot
2026-08-31 7:13 ` [RFC PATCH v2 4/4] KVM: x86: Add optional KVM_EXPORT_VCPU and KVM_IMPORT_VCPU Tony Lindgren
3 siblings, 1 reply; 9+ messages in thread
From: Tony Lindgren @ 2026-08-31 7:13 UTC (permalink / raw)
To: Paolo Bonzini, Sean Christopherson
Cc: Peter Xu, Artem Bityutskiy, Fabiano Rosas, Jon Grimm,
Pankaj Gupta, Tom Lendacky, Marc Zyngier, Oliver Upton,
Steven Price, Anup Patel, Samuel Ortiz,
Jakub Růžička, Jörg Rödel ,
Vishal Annapurve, Elena Reshetova, Kai Huang, Kishen Maloor,
Mika Westerberg, Peter Fang, Rick Edgecombe, Xiaoyao Li, Xu Yilun,
kvm
Add support to export and import KVM memory for cases where the memory
is only accessible to the guest. Live migration of confidential computing
needs help of KVM for the vendor specific calls at least for TDX.
Introduce optional KVM_EXPORT_MEMORY and KVM_IMPORT_MEMORY.
Based on earlier code by Wei Wang <wei.w.wang@intel.com>.
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Assisted-by: Claude-Code:claude-opus-5 checkpatch
[ used AI to review and simplify the code ]
Signed-off-by: Tony Lindgren <tony.lindgren@linux.intel.com>
---
arch/x86/include/asm/kvm-x86-ops.h | 2 ++
arch/x86/include/asm/kvm_host.h | 2 ++
arch/x86/kvm/x86.c | 37 ++++++++++++++++++++++++++++++
include/uapi/linux/kvm.h | 13 +++++++++++
4 files changed, 54 insertions(+)
diff --git a/arch/x86/include/asm/kvm-x86-ops.h b/arch/x86/include/asm/kvm-x86-ops.h
index ac080b556b0c8..173d0c4f1115e 100644
--- a/arch/x86/include/asm/kvm-x86-ops.h
+++ b/arch/x86/include/asm/kvm-x86-ops.h
@@ -150,6 +150,8 @@ 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)
+KVM_X86_OP_OPTIONAL(export_memory)
+KVM_X86_OP_OPTIONAL(import_memory)
#endif
#undef KVM_X86_OP
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index d9291a8a97bb1..9a517bfc2f3a6 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -2012,6 +2012,8 @@ struct kvm_x86_ops {
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);
+ int (*export_memory)(struct kvm *kvm, struct kvm_memory_transfer *mem);
+ int (*import_memory)(struct kvm *kvm, struct kvm_memory_transfer *mem);
};
struct kvm_x86_nested_ops {
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 7064fd709e56d..8a99c665008a3 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -7258,6 +7258,37 @@ long kvm_arch_vcpu_unlocked_ioctl(struct file *filp, unsigned int ioctl,
return -ENOIOCTLCMD;
}
+static int kvm_vm_ioctl_transfer_memory(struct kvm *kvm, bool import,
+ void __user *argp)
+{
+ struct kvm_memory_transfer mem;
+ int r;
+
+ if (!kvm_x86_call(cap_live_migration)(kvm) ||
+ (import && !kvm_x86_ops.import_memory) ||
+ (!import && !kvm_x86_ops.export_memory))
+ return -ENOTTY;
+
+ if (copy_from_user(&mem, argp, sizeof(mem)))
+ return -EFAULT;
+
+ if (mem.reserved || mem.buf.reserved || !mem.nr_gfns)
+ return -EINVAL;
+
+ if (import)
+ r = kvm_x86_call(import_memory)(kvm, &mem);
+ else
+ r = kvm_x86_call(export_memory)(kvm, &mem);
+ if (r > 0)
+ r = -EIO;
+
+ /* Copy back also on an error to report a partially done transfer */
+ if (copy_to_user(argp, &mem, sizeof(mem)))
+ return -EFAULT;
+
+ return r;
+}
+
int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
{
struct kvm *kvm = filp->private_data;
@@ -7639,6 +7670,12 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
return -EFAULT;
break;
}
+ case KVM_EXPORT_MEMORY:
+ r = kvm_vm_ioctl_transfer_memory(kvm, false, argp);
+ break;
+ case KVM_IMPORT_MEMORY:
+ r = kvm_vm_ioctl_transfer_memory(kvm, true, argp);
+ break;
default:
r = -ENOTTY;
}
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index e5b227d3a8e40..666bbdf220d65 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -1493,6 +1493,10 @@ struct kvm_enc_region {
#define KVM_GET_SREGS2 _IOR(KVMIO, 0xcc, struct kvm_sregs2)
#define KVM_SET_SREGS2 _IOW(KVMIO, 0xcd, struct kvm_sregs2)
+/* Available with KVM_CAP_LIVE_MIGRATION */
+#define KVM_EXPORT_MEMORY _IOWR(KVMIO, 0xe5, struct kvm_memory_transfer)
+#define KVM_IMPORT_MEMORY _IOWR(KVMIO, 0xe6, struct kvm_memory_transfer)
+
#define KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE (1 << 0)
#define KVM_DIRTY_LOG_INITIALLY_SET (1 << 1)
@@ -1692,4 +1696,13 @@ struct kvm_migrate_cmd {
struct kvm_transfer_buffer buf;
};
+struct kvm_memory_transfer {
+ __u64 gfns;
+ __u32 nr_gfns;
+ __u16 id;
+ __u16 flags;
+ __u64 reserved;
+ struct kvm_transfer_buffer buf;
+};
+
#endif /* __LINUX_KVM_H */
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [RFC PATCH v2 3/4] KVM: x86: Add optional KVM_EXPORT_MEMORY and KVM_IMPORT_MEMORY
2026-08-31 7:13 ` [RFC PATCH v2 3/4] KVM: x86: Add optional KVM_EXPORT_MEMORY and KVM_IMPORT_MEMORY Tony Lindgren
@ 2026-08-31 7:23 ` sashiko-bot
0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-08-31 7:23 UTC (permalink / raw)
To: Tony Lindgren; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Unvalidated UAPI fields `flags` and `id` in `struct kvm_memory_transfer` can lead to ABI breakage.
--
commit b6f49e80a58eebaaa2a6d123950fd36709972a10
Author: Tony Lindgren <tony.lindgren@linux.intel.com>
KVM: x86: Add optional KVM_EXPORT_MEMORY and KVM_IMPORT_MEMORY
This commit adds support to export and import KVM memory for cases where
the memory is only accessible to the guest. It introduces the optional
KVM_EXPORT_MEMORY and KVM_IMPORT_MEMORY ioctls to assist with live
migration of confidential computing.
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 7064fd709e56d..8a99c665008a3 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
[ ... ]
> @@ -7258,6 +7258,37 @@ long kvm_arch_vcpu_unlocked_ioctl(struct file *filp, unsigned int ioctl,
> return -ENOIOCTLCMD;
> }
>
> +static int kvm_vm_ioctl_transfer_memory(struct kvm *kvm, bool import,
> + void __user *argp)
> +{
> + struct kvm_memory_transfer mem;
> + int r;
> +
> + if (!kvm_x86_call(cap_live_migration)(kvm) ||
> + (import && !kvm_x86_ops.import_memory) ||
> + (!import && !kvm_x86_ops.export_memory))
> + return -ENOTTY;
> +
> + if (copy_from_user(&mem, argp, sizeof(mem)))
> + return -EFAULT;
> +
> + if (mem.reserved || mem.buf.reserved || !mem.nr_gfns)
> + return -EINVAL;
[Severity: Medium]
Does this input validation for the kvm_memory_transfer UAPI struct miss
checking mem.flags == 0 and mem.id == 0?
Failing to validate that unused UAPI fields are zero allows userspace to pass
uninitialized garbage. If KVM later assigns specific meaning to these fields,
older applications that unintentionally passed non-zero values could break,
leading to an ABI compatibility issue.
Standard Linux UAPI design usually requires enforcing these unused or reserved
fields to be zero for future extensibility.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260831071304.762939-1-tony.lindgren@linux.intel.com?part=3
^ permalink raw reply [flat|nested] 9+ messages in thread
* [RFC PATCH v2 4/4] KVM: x86: Add optional KVM_EXPORT_VCPU and KVM_IMPORT_VCPU
2026-08-31 7:13 [RFC PATCH v2 0/4] Add KVM API for confidential guest live migration Tony Lindgren
` (2 preceding siblings ...)
2026-08-31 7:13 ` [RFC PATCH v2 3/4] KVM: x86: Add optional KVM_EXPORT_MEMORY and KVM_IMPORT_MEMORY Tony Lindgren
@ 2026-08-31 7:13 ` Tony Lindgren
2026-08-31 7:23 ` sashiko-bot
3 siblings, 1 reply; 9+ messages in thread
From: Tony Lindgren @ 2026-08-31 7:13 UTC (permalink / raw)
To: Paolo Bonzini, Sean Christopherson
Cc: Peter Xu, Artem Bityutskiy, Fabiano Rosas, Jon Grimm,
Pankaj Gupta, Tom Lendacky, Marc Zyngier, Oliver Upton,
Steven Price, Anup Patel, Samuel Ortiz,
Jakub Růžička, Jörg Rödel ,
Vishal Annapurve, Elena Reshetova, Kai Huang, Kishen Maloor,
Mika Westerberg, Peter Fang, Rick Edgecombe, Xiaoyao Li, Xu Yilun,
kvm
Add support to export and import VCPU for cases where the VCPU state is
only accessible to the guest. Live migration of confidential computing
needs help of KVM for the firmware specific calls at least for TDX.
Introduce optional KVM_EXPORT_VCPU and KVM_IMPORT_VCPU.
Based on earlier code by Wei Wang <wei.w.wang@intel.com>.
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Tony Lindgren <tony.lindgren@linux.intel.com>
---
arch/x86/include/asm/kvm-x86-ops.h | 2 ++
arch/x86/include/asm/kvm_host.h | 2 ++
arch/x86/kvm/x86.c | 40 ++++++++++++++++++++++++++++++
include/uapi/linux/kvm.h | 8 ++++++
4 files changed, 52 insertions(+)
diff --git a/arch/x86/include/asm/kvm-x86-ops.h b/arch/x86/include/asm/kvm-x86-ops.h
index 173d0c4f1115e..7f110f80d6f82 100644
--- a/arch/x86/include/asm/kvm-x86-ops.h
+++ b/arch/x86/include/asm/kvm-x86-ops.h
@@ -152,6 +152,8 @@ KVM_X86_OP_OPTIONAL_RET0(cap_live_migration)
KVM_X86_OP_OPTIONAL(migrate_cmd)
KVM_X86_OP_OPTIONAL(export_memory)
KVM_X86_OP_OPTIONAL(import_memory)
+KVM_X86_OP_OPTIONAL(export_vcpu)
+KVM_X86_OP_OPTIONAL(import_vcpu)
#endif
#undef KVM_X86_OP
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 9a517bfc2f3a6..b6362408dab80 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -2014,6 +2014,8 @@ struct kvm_x86_ops {
int (*migrate_cmd)(struct kvm *kvm, struct kvm_migrate_cmd *cmd);
int (*export_memory)(struct kvm *kvm, struct kvm_memory_transfer *mem);
int (*import_memory)(struct kvm *kvm, struct kvm_memory_transfer *mem);
+ int (*export_vcpu)(struct kvm_vcpu *vcpu, struct kvm_vcpu_transfer *vcpu_state);
+ int (*import_vcpu)(struct kvm_vcpu *vcpu, struct kvm_vcpu_transfer *vcpu_state);
};
struct kvm_x86_nested_ops {
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 8a99c665008a3..e8385326894b1 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -6189,6 +6189,38 @@ static int kvm_get_reg_list(struct kvm_vcpu *vcpu,
return 0;
}
+static int kvm_vcpu_ioctl_transfer_vcpu(struct kvm_vcpu *vcpu, bool import,
+ void __user *argp)
+{
+ struct kvm_vcpu_transfer vcpu_state;
+ struct kvm *kvm = vcpu->kvm;
+ int r;
+
+ if (!kvm_x86_call(cap_live_migration)(kvm) ||
+ (import && !kvm_x86_ops.import_vcpu) ||
+ (!import && !kvm_x86_ops.export_vcpu))
+ return -ENOTTY;
+
+ if (copy_from_user(&vcpu_state, argp, sizeof(vcpu_state)))
+ return -EFAULT;
+
+ if (vcpu_state.reserved || vcpu_state.buf.reserved)
+ return -EINVAL;
+
+ if (import)
+ r = kvm_x86_call(import_vcpu)(vcpu, &vcpu_state);
+ else
+ r = kvm_x86_call(export_vcpu)(vcpu, &vcpu_state);
+ if (r > 0)
+ r = -EIO;
+
+ /* Copy back also on an error to report a partially done transfer */
+ if (copy_to_user(argp, &vcpu_state, sizeof(vcpu_state)))
+ r = -EFAULT;
+
+ return r;
+}
+
long kvm_arch_vcpu_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg)
{
@@ -6659,6 +6691,14 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
goto out;
r = kvm_x86_ops.vcpu_mem_enc_ioctl(vcpu, argp);
break;
+ case KVM_EXPORT_VCPU: {
+ r = kvm_vcpu_ioctl_transfer_vcpu(vcpu, false, argp);
+ break;
+ }
+ case KVM_IMPORT_VCPU: {
+ r = kvm_vcpu_ioctl_transfer_vcpu(vcpu, true, argp);
+ break;
+ }
default:
r = -EINVAL;
}
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 666bbdf220d65..0a9aa126daadb 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -1496,6 +1496,8 @@ struct kvm_enc_region {
/* Available with KVM_CAP_LIVE_MIGRATION */
#define KVM_EXPORT_MEMORY _IOWR(KVMIO, 0xe5, struct kvm_memory_transfer)
#define KVM_IMPORT_MEMORY _IOWR(KVMIO, 0xe6, struct kvm_memory_transfer)
+#define KVM_EXPORT_VCPU _IOWR(KVMIO, 0xe7, struct kvm_vcpu_transfer)
+#define KVM_IMPORT_VCPU _IOWR(KVMIO, 0xe8, struct kvm_vcpu_transfer)
#define KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE (1 << 0)
#define KVM_DIRTY_LOG_INITIALLY_SET (1 << 1)
@@ -1705,4 +1707,10 @@ struct kvm_memory_transfer {
struct kvm_transfer_buffer buf;
};
+struct kvm_vcpu_transfer {
+ __u32 flags;
+ __u32 reserved;
+ struct kvm_transfer_buffer buf;
+};
+
#endif /* __LINUX_KVM_H */
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [RFC PATCH v2 4/4] KVM: x86: Add optional KVM_EXPORT_VCPU and KVM_IMPORT_VCPU
2026-08-31 7:13 ` [RFC PATCH v2 4/4] KVM: x86: Add optional KVM_EXPORT_VCPU and KVM_IMPORT_VCPU Tony Lindgren
@ 2026-08-31 7:23 ` sashiko-bot
0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-08-31 7:23 UTC (permalink / raw)
To: Tony Lindgren; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Missing validation of the flags field in UAPI struct kvm_vcpu_transfer breaks forward compatibility.
--
commit 4d7dccde0750ca7fd34158829ad4120d967ac2c3
Author: Tony Lindgren <tony.lindgren@linux.intel.com>
KVM: x86: Add optional KVM_EXPORT_VCPU and KVM_IMPORT_VCPU
This commit adds support to export and import a VCPU for cases where the
VCPU state is only accessible to the guest. It introduces the new
KVM_EXPORT_VCPU and KVM_IMPORT_VCPU ioctls, along with the required
kvm_vcpu_transfer structure.
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 8a99c665008a3..e8385326894b1 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
[ ... ]
> @@ -6189,6 +6189,38 @@ static int kvm_get_reg_list(struct kvm_vcpu *vcpu,
> return 0;
> }
>
> +static int kvm_vcpu_ioctl_transfer_vcpu(struct kvm_vcpu *vcpu, bool import,
> + void __user *argp)
> +{
> + struct kvm_vcpu_transfer vcpu_state;
> + struct kvm *kvm = vcpu->kvm;
> + int r;
[ ... ]
> + if (copy_from_user(&vcpu_state, argp, sizeof(vcpu_state)))
> + return -EFAULT;
> +
> + if (vcpu_state.reserved || vcpu_state.buf.reserved)
> + return -EINVAL;
[Severity: High]
Should we also validate the flags field here to ensure forward compatibility?
The new kvm_vcpu_transfer structure introduces a flags field, but this
validation step only explicitly rejects non-zero reserved fields.
If the kernel silently ignores non-zero flags, userspace might
inadvertently pass uninitialized or arbitrary values without receiving
an error. If KVM later assigns meaning to these flags, old userspace
programs that have been unknowingly passing garbage could unexpectedly
trigger new behaviors or break.
Would it be appropriate to require that vcpu_state.flags is zero for now?
> +
> + if (import)
> + r = kvm_x86_call(import_vcpu)(vcpu, &vcpu_state);
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260831071304.762939-1-tony.lindgren@linux.intel.com?part=4
^ permalink raw reply [flat|nested] 9+ messages in thread