All of lore.kernel.org
 help / color / mirror / Atom feed
From: Artem Bityutskiy <dedekind1@gmail.com>
To: Tony Lindgren <tony.lindgren@linux.intel.com>,
	Paolo Bonzini <pbonzini@redhat.com>,
	Sean Christopherson <seanjc@google.com>
Cc: "Peter Xu" <peterx@redhat.com>, "Fabiano Rosas" <farosas@suse.de>,
	"Jon Grimm" <Jon.Grimm@amd.com>,
	"Pankaj Gupta" <pankaj.gupta@amd.com>,
	"Tom Lendacky" <thomas.lendacky@amd.com>,
	"Marc Zyngier" <maz@kernel.org>,
	"Oliver Upton" <oliver.upton@linux.dev>,
	"Steven Price" <steven.price@arm.com>,
	"Anup Patel" <anup@brainfault.org>,
	"Samuel Ortiz" <sameo@rivosinc.com>,
	"Jakub Růžička" <jakub.ruzicka@matfyz.cz>,
	"Jörg Rödel" <joro@8bytes.org>,
	"Vishal Annapurve" <vannapurve@google.com>,
	"Elena Reshetova" <elena.reshetova@intel.com>,
	"Kai Huang" <kai.huang@intel.com>,
	"Kishen Maloor" <kishen.maloor@intel.com>,
	"Mika Westerberg" <mika.westerberg@linux.intel.com>,
	"Peter Fang" <peter.fang@intel.com>,
	"Rick Edgecombe" <rick.p.edgecombe@intel.com>,
	"Xiaoyao Li" <xiaoyao.li@intel.com>,
	"Xu Yilun" <yilun.xu@linux.intel.com>,
	kvm@vger.kernel.org
Subject: Re: [RFC PATCH v2 0/4] Add KVM API for confidential guest live migration
Date: Fri, 04 Sep 2026 21:24:25 +0300	[thread overview]
Message-ID: <d78207fcc5936b5822b708238d862b0e10f9f5c3.camel@gmail.com> (raw)
In-Reply-To: <20260831071304.762939-1-tony.lindgren@linux.intel.com>

On Mon, 2026-08-31 at 10:13 +0300, Tony Lindgren wrote:
> Tom, since you mentioned that AMD SEV-SNP and Intel TDX live migration
> sound similar, can you please take a look how the API might work for
> SEV-SNP?

The presented example uAPIs were designed to fit the TDX live migration
flow, with the intent that they could also be used by other CoCo VMs.

It would be super great if someone could commend on how suitable these
uAPIs are for AMD and ARM flows.

AFAIU, what is generic in the presented uAPI is more of usage pattern.

- The order in which QEMU calls them.
- The idea that QEMU/KVM is a transport for opaque blobs.

The proposed container - 'struct kvm_transfer_buffer' - only has address
and a size. The vendor defines the layout of the data in it.

Some example high-level topics that would be nice to get feedback on:

- Can we come up with a single set of generic migration uAPIs for different
  CoCo models?
- Or should some uAPIs be generic while others are vendor-specific?
- Or should each CoCo model have its own vendor-specific set of migration
  uAPIs?
- Should the same uAPIs also support traditional VMs? But the only use-case
  I imagine here is "for testing purposes".

> Artem has put together a brief description below of the example API and the
> migration flow:

.. snip ...

> Migration flow
> ==============
> 
>  Source host                                      Destination host
>  ===========                                      ================
> 
>  CMD(SETUP/SESSION)          <--- setup msgs ---> CMD(SETUP/SESSION)
>        |    (repeated)                                  |
>  CMD(SETUP/IMMUTABLE_STATE)  - immutable state -> CMD(SETUP/IMMUTABLE_STATE)
>        |                                                |
>  KVM_GET_DIRTY_LOG                                      |
>  KVM_EXPORT_MEMORY           --- memory data ---> KVM_IMPORT_MEMORY
>  CMD(ITERATION)              --- epoch token ---> CMD(ITERATION)
>        |    (repeat until convergence)                  |
>  CMD(STOP_AND_COPY/PAUSE)                               |
>  CMD(STOP_AND_COPY/TD_STATE) --- VM state ------> CMD(STOP_AND_COPY/TD_STATE)
>  KVM_EXPORT_VCPU             --- vCPU state ----> KVM_IMPORT_VCPU
>  KVM_EXPORT_MEMORY           -- final memory ---> KVM_IMPORT_MEMORY
>  CMD(ITERATION/DONE)         --- start token ---> CMD(ITERATION)
>        |                                                |
>  CMD(END)                                         CMD(END)

... snip ...


As I mentioned, the example uAPI is modeled around the TDX migration flow.
In case it helps the reader, here is a summary of that flow that was
presented in PUCK.

It describes what the TDX module offers today and focuses on pre-copy
migration. This is our interpretation of the TDX specifications, not a
specification itself, and may contain errors or omissions. Please refer to
the official TDX specifications for authoritative information.

Migration Overview
------------------

In TDX, the TDX module implements the migration logic. The VMM drives
migration by issuing seamcalls to the source and destination TDX modules and
transports the resulting encrypted blobs between them. The VMM does not need
to know the contents of those blobs.

The TDX security model enforces two hard rules:

- Only one instance of the TD may run at a time. Either the source or the
  destination may run, but never both. In other words, cloning a TD is not
  allowed.
- When migration completes, the destination must have the same memory and
  vCPU state as the source. It must not end up with a partial or mixed
  state.

Simple Overview
---------------

Run the migration setup session
  |
  v
Transfer immutable TD state
  |
  v
Copy dirty memory pages while the TD runs <-------+
  |                                               |
  +-- iterate until convergence criteria is met --+
  |
  v
Pause the source TD and copy the remaining state
  |
  v
Start the destination TD

The migration process starts with a setup session. During the setup session,
the source and destination TDX modules exchange encrypted blobs and
establish migration encryption keys. For example, these keys protect memory
contents transferred during migration.

Next, the source transfers the immutable TD state to the destination and
initializes the destination TD. This state includes the read-only VM data,
such as its vCPU count and topology.

The source and destination then perform iterative memory-copy rounds. In
each round, the source scans for memory pages that need to be migrated and
exports them in encrypted form. The destination imports the pages. The
rounds continue until the number of pages that change between rounds is
small enough to meet the convergence criteria.

The source TD is then paused. The VMM transfers the remaining TD state, such
as vCPU state, and the final dirty memory pages. Finally, the destination TD
is started and the migration completes.

Notice that the VMM's role in this process is to issue the required
seamcalls and send encrypted blobs between the source and destination. The
VMM does not need to know the contents of those blobs.

More Detailed Overview
----------------------

The following diagram shows the TDX seamcalls used by the source and
destination:

 Source host                                          Destination host
 ===========                                          ================

 TDH.MIG.SETUP        -- crypto keys, attestation ->  TDH.MIG.SETUP
       |                                                    |
 TDH.EXPORT.STATE.IMMUTABLE -- read-only TD state ->
TDH.IMPORT.STATE.IMMUTABLE
       |                                                    |
 TDH.MEM.SCAN.RANGE                                         |
 TDH.MEM.TRACK + IPIs                                       |
 TDH.EXPORT.MEM        ------ memory data --------->  TDH.IMPORT.MEM
 TDH.EXPORT.TRACK      ------ epoch token --------->  TDH.IMPORT.TRACK
       |                                                    |
 TDH.EXPORT.PAUSE                                           |
       |                                                    |
 TDH.EXPORT.STATE.TD   ------ global TD state ----->  TDH.IMPORT.STATE.TD
       |                                                    |
 TDH.EXPORT.STATE.VP   ------ vCPU state ---------->  TDH.IMPORT.STATE.VP
       |                                                    |
 TDH.MEM.SCAN.COMP                                          |
 TDH.MEM.TRACK + IPIs                                       |
 TDH.EXPORT.MEM        ------ final memory data --->  TDH.IMPORT.MEM
 TDH.EXPORT.TRACK      ------ start token --------->  TDH.IMPORT.TRACK
                                                            |
                                                      TDH.IMPORT.END

The source and destination go through the following stages.

Setup
-----

The VMM issues TDH.MIG.SETUP on the source and destination TDX modules
iteratively to perform the setup session. The modules return status and may
also return an encrypted blob, which the VMM passes between the two sides.
In other words, the migration protocol is between the two TDX modules, while
the VMM is simply the transport mechanism. The setup session performs mutual
attestation, establishes trust between the modules, establishes migration
encryption keys, and loads the migration policy. It completes when the TDX
module returns success.

Immutable State Transfer
------------------------

The source calls TDH.EXPORT.STATE.IMMUTABLE to export the immutable TD
state. The destination VMM creates the destination TD skeleton and
configures migration streams, then calls TDH.IMPORT.STATE.IMMUTABLE, which
finalizes the destination TD initialization.

Iterative Memory Copy
---------------------

While the source TD continues running, the source and destination run
iterative memory copy rounds:

- The source calls TDH.MEM.SCAN.RANGE to find migration candidate pages.
- The source calls TDH.MEM.TRACK and sends IPIs to the TD's vCPUs in order
  to ensure the dirty page scanning algorithm correctness.
- The source calls TDH.EXPORT.MEM to export private memory pages, which the
  VMM sends to the destination.
- The destination calls TDH.IMPORT.MEM to import the received memory pages.
- The source calls TDH.EXPORT.TRACK to generate an epoch token. The VMM
  sends it to the destination, which calls TDH.IMPORT.TRACK to consume the
  token. This verifies that all data exported from the source was imported
  on the destination.

The rounds continue until the number of pages that change between rounds is
small enough to meet the convergence criteria.

Stop and Copy
-------------

The VMM pauses the source TD, which begins the downtime period, then calls
TDH.EXPORT.PAUSE to start the TDX-enforced blackout period. The source then
calls TDH.EXPORT.STATE.TD to export mutable TD-scope state and
TDH.EXPORT.STATE.VP to export mutable state for each vCPU. It then performs
the final dirty page scan, runs TDH.MEM.TRACK and sends IPIs, and calls
TDH.EXPORT.MEM to export the final dirty pages as encrypted blobs.

The destination calls TDH.IMPORT.STATE.TD to import mutable TD-scope state
and TDH.IMPORT.STATE.VP to import the mutable state of each vCPU. It calls
TDH.IMPORT.MEM to import the final dirty pages.

After exporting the final dirty pages, the source's last migration seamcall
is TDH.EXPORT.TRACK with IN_ORDER_DONE=1, which generates the start token.
The VMM sends the start token to the destination. The destination calls
TDH.IMPORT.TRACK with this token. This verifies that the mutable TD state
has been imported and allows the destination to start the TD. Finally, the
destination calls TDH.IMPORT.END, which ends the migration.

  parent reply	other threads:[~2026-09-04 18:24 UTC|newest]

Thread overview: 82+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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:20   ` sashiko-bot
2026-09-18 11:35   ` Peter Xu
2026-09-21  4:20     ` Tony Lindgren
2026-09-24  1:50     ` Wei Wang
2026-09-24  4:51       ` 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:23   ` sashiko-bot
2026-09-01  6:03     ` Tony Lindgren
2026-09-07 11:53   ` Tony Lindgren
2026-09-07 13:15     ` Jörg Rödel
2026-09-07 13:32       ` Artem Bityutskiy
2026-09-08  4:15         ` Tony Lindgren
2026-09-08  4:43         ` Tony Lindgren
2026-09-09  0:22           ` Kishen Maloor
2026-09-09  6:57             ` Tony Lindgren
2026-09-10  1:11               ` Kishen Maloor
2026-09-10  6:33                 ` Tony Lindgren
2026-09-11  1:40                   ` Kishen Maloor
2026-09-11  4:23                     ` Tony Lindgren
2026-09-15  0:14                       ` Kishen Maloor
2026-09-15  4:44                         ` Tony Lindgren
2026-09-15 15:53                           ` Kishen Maloor
2026-09-16  5:09                             ` Tony Lindgren
2026-09-17  3:31                               ` Kishen Maloor
2026-09-17  6:42                                 ` Tony Lindgren
2026-09-18  4:32                                   ` Kishen Maloor
2026-09-18  5:58                                     ` Tony Lindgren
2026-09-21  0:13                                       ` Kishen Maloor
2026-09-21  6:52                                         ` Tony Lindgren
2026-09-21  9:24                                           ` Tony Lindgren
2026-09-21 10:58                                             ` Tony Lindgren
2026-09-22  3:57                                           ` Kishen Maloor
2026-09-22  5:25                                             ` Tony Lindgren
2026-09-23  0:38                                               ` Kishen Maloor
2026-09-23  6:04                                                 ` Tony Lindgren
2026-09-24  5:53                                                   ` Kishen Maloor
2026-09-24  6:59                                                     ` Tony Lindgren
2026-09-18  4:33   ` Kishen Maloor
2026-09-21  5:58     ` Tony Lindgren
2026-09-21  6:56       ` Tony Lindgren
2026-09-22  3:56         ` Kishen Maloor
2026-09-22  6:27           ` Tony Lindgren
2026-09-23  0:37             ` Kishen Maloor
2026-09-23  6:50               ` Tony Lindgren
2026-09-24  5:34                 ` Kishen Maloor
2026-09-24  7:15                   ` Tony Lindgren
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
2026-09-01  6:10     ` 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
2026-08-31  7:23   ` sashiko-bot
2026-09-01  6:12     ` Tony Lindgren
2026-09-04 18:24 ` Artem Bityutskiy [this message]
2026-09-17 21:27   ` [RFC PATCH v2 0/4] Add KVM API for confidential guest live migration Peter Xu
2026-09-18 12:46     ` Artem Bityutskiy
2026-09-18 15:53       ` Peter Xu
2026-09-22  8:09         ` Artem Bityutskiy
2026-09-22  9:42           ` Tony Lindgren
2026-09-22 11:54             ` Artem Bityutskiy
2026-09-23  4:20               ` Tony Lindgren
2026-09-22 21:18           ` Peter Xu
2026-09-23 12:05             ` Artem Bityutskiy
2026-09-24 21:19               ` Peter Xu
2026-09-28 14:15                 ` Artem Bityutskiy
2026-09-29 21:05                   ` Peter Xu
2026-10-02 19:57                     ` Artem Bityutskiy
2026-10-07 20:00                       ` Peter Xu
2026-09-23 15:28           ` Serge Hallyn (AMD)
2026-09-20 23:56     ` Kishen Maloor
2026-09-23 21:36       ` Peter Xu
2026-09-24  4:27         ` Kishen Maloor
2026-09-25 14:18           ` Peter Xu
2026-09-29  1:28             ` Kishen Maloor
2026-09-30 20:42               ` Peter Xu
2026-10-07  4:27                 ` Kishen Maloor
2026-10-07 20:13                   ` Peter Xu
2026-09-18 18:36 ` Ionut Mihalcea
2026-09-21  4:35   ` Tony Lindgren
2026-09-25 16:03 ` Serge Hallyn (AMD)
2026-09-28  3:24   ` Kishen Maloor

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d78207fcc5936b5822b708238d862b0e10f9f5c3.camel@gmail.com \
    --to=dedekind1@gmail.com \
    --cc=Jon.Grimm@amd.com \
    --cc=anup@brainfault.org \
    --cc=elena.reshetova@intel.com \
    --cc=farosas@suse.de \
    --cc=jakub.ruzicka@matfyz.cz \
    --cc=joro@8bytes.org \
    --cc=kai.huang@intel.com \
    --cc=kishen.maloor@intel.com \
    --cc=kvm@vger.kernel.org \
    --cc=maz@kernel.org \
    --cc=mika.westerberg@linux.intel.com \
    --cc=oliver.upton@linux.dev \
    --cc=pankaj.gupta@amd.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.fang@intel.com \
    --cc=peterx@redhat.com \
    --cc=rick.p.edgecombe@intel.com \
    --cc=sameo@rivosinc.com \
    --cc=seanjc@google.com \
    --cc=steven.price@arm.com \
    --cc=thomas.lendacky@amd.com \
    --cc=tony.lindgren@linux.intel.com \
    --cc=vannapurve@google.com \
    --cc=xiaoyao.li@intel.com \
    --cc=yilun.xu@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.