[RFC PATCH 28/46] KVM: caretaker: Add Caretaker control block and architecture ops headers
From: Pasha Tatashin
Date: Sun Sep 20 2026 - 15:57:49 EST
Define struct kvm_caretaker_cb, struct kvm_caretaker_ops, and
KVM_CAP_CARETAKER documentation for OrphanVM on-core execution.
Signed-off-by: Pasha Tatashin <pasha.tatashin@xxxxxxxxxx>
---
Documentation/virt/kvm/api.rst | 16 ++
include/linux/kho/abi/kvm.h | 112 ++++++++++-
include/linux/kvm_caretaker.h | 341 +++++++++++++++++++++++++++++++++
include/linux/kvm_host.h | 10 +
include/uapi/linux/kvm.h | 1 +
5 files changed, 479 insertions(+), 1 deletion(-)
create mode 100644 include/linux/kvm_caretaker.h
diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index e0430cc750c9..a5c7a48617c3 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -9600,6 +9600,22 @@ 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_CARETAKER
+----------------------
+
+:Architectures: x86, arm64
+
+This capability, if ``KVM_CHECK_EXTENSION`` returns a non-zero value,
+indicates that the host kernel supports Caretaker on-core guest execution
+across kexec-based host live updates.
+
+When both a vCPU file descriptor and its backing physical CPU's preservation
+file descriptor (``/sys/devices/system/cpu/cpuX/preserve``) are preserved in a
+Live Update Orchestrator (LUO) session, KVM schedules the vCPU to continue
+executing on-core within the preserved Caretaker environment throughout the
+host kexec transition, rather than pausing vCPU execution until the incoming
+kernel re-attaches.
+
9. Known KVM API problems
=========================
diff --git a/include/linux/kho/abi/kvm.h b/include/linux/kho/abi/kvm.h
index 166a0a2f13c8..85fafb786747 100644
--- a/include/linux/kho/abi/kvm.h
+++ b/include/linux/kho/abi/kvm.h
@@ -30,10 +30,12 @@
/**
* struct kvm_luo_ser - Main serialization structure for a KVM VM.
- * @type: The type of VM.
+ * @type: The type of VM.
+ * @kho_folios: Preservation pointer to VM-wide KHO-preserved folios.
*/
struct kvm_luo_ser {
u64 type;
+ DECLARE_KHOSER_PTR(kho_folios, struct kvm_kho_folios_ser *);
} __packed;
/* The compatibility string for KVM VM file handler */
@@ -47,18 +49,126 @@ enum kvm_vcpu_luo_flags {
KVM_VCPU_LUO_FLAG_CARETAKER = BIT(0),
};
+/**
+ * enum kvm_caretaker_pcpu - Special Caretaker physical CPU identifiers
+ * @KVM_CARETAKER_INVALID_PCPU: Unassigned physical CPU identifier.
+ */
+enum kvm_caretaker_pcpu {
+ KVM_CARETAKER_INVALID_PCPU = U32_MAX,
+};
+
+/**
+ * enum kvm_caretaker_state - Caretaker vCPU execution state machine
+ * @KVM_CARETAKER_PAUSED: Initial state upon preservation and between
+ * oncore_sched time-sharing quantums (or when parked
+ * after an unhandled VM exit). Live architectural
+ * state is fully serialized in @arch_state.
+ * @KVM_CARETAKER_RUNNING: Actively executing a time-sharing quantum on the
+ * preserved physical CPU. Hardware registers and
+ * VMCS/VMCB/EL2 state are live on silicon; @arch_state
+ * in memory is stale until the quantum exits.
+ * @KVM_CARETAKER_STOPPING: Host requested reclaim while in
+ * %KVM_CARETAKER_RUNNING and sent a physical IPI kick.
+ * Caretaker will exit guest mode, serialize live
+ * hardware state into @arch_state, and transition to
+ * %KVM_CARETAKER_STOPPED.
+ * @KVM_CARETAKER_STOPPED: Terminal state. Caretaker execution has permanently
+ * ceased and @arch_state is valid in memory. Reached
+ * either directly via host cmpxchg from
+ * %KVM_CARETAKER_PAUSED, or by the preserved CPU from
+ * %KVM_CARETAKER_STOPPING after serialization completes.
+ *
+ * State transitions are coordinated locklessly via atomic cmpxchg(&cb->state):
+ * - Each scheduler quantum on the preserved CPU transitions
+ * %KVM_CARETAKER_PAUSED -> %KVM_CARETAKER_RUNNING on entry and
+ * %KVM_CARETAKER_RUNNING -> %KVM_CARETAKER_PAUSED after serializing guest
+ * state on quantum exit.
+ * - When host KVM reclaims the vCPU (kvm_caretaker_wait_for_attach()):
+ * 1. If @cb->state is %KVM_CARETAKER_PAUSED, host atomically transitions it
+ * to %KVM_CARETAKER_STOPPED in 0 ns; if the preserved CPU later attempts
+ * to start a quantum, its cmpxchg(%KVM_CARETAKER_PAUSED ->
+ * %KVM_CARETAKER_RUNNING) fails and it immediately exits.
+ * 2. If @cb->state is %KVM_CARETAKER_RUNNING, host atomically transitions
+ * it to %KVM_CARETAKER_STOPPING, sends an IPI to preempt guest mode, and
+ * spins until the preserved CPU finishes detach_serialize() and stores
+ * %KVM_CARETAKER_STOPPED.
+ */
+enum kvm_caretaker_state {
+ KVM_CARETAKER_PAUSED = 0,
+ KVM_CARETAKER_RUNNING = 1,
+ KVM_CARETAKER_STOPPING = 2,
+ KVM_CARETAKER_STOPPED = 3,
+};
+
+/**
+ * struct kvm_caretaker_telemetry_ser - Serialized Caretaker execution telemetry
+ * @total_runs: Total guest entry attempts across Caretaker quantums.
+ * @total_exits: Total VM exits decoded during Caretaker execution.
+ * @stall_count: Number of times Caretaker exited due to stall or error.
+ * @last_exit_reason: Raw architecture exit reason of most recent VM exit.
+ * @last_exit_rip: Guest instruction pointer at most recent VM exit.
+ * @stall_exit_reason: Raw architecture exit reason or error at stall.
+ * @stall_exit_rip: Guest instruction pointer at stall.
+ */
+struct kvm_caretaker_telemetry_ser {
+ u64 total_runs;
+ u64 total_exits;
+ u64 stall_count;
+ u64 last_exit_reason;
+ u64 last_exit_rip;
+ u64 stall_exit_reason;
+ u64 stall_exit_rip;
+} __packed;
+
+/**
+ * struct kvm_kho_folios_ser - Serialized list of KHO-preserved folios for a VM
+ * @nr_folios: Number of physical folio addresses in @folios_pa.
+ * @folios_pa: Physical addresses of folios preserved via kho_preserve_folio().
+ */
+struct kvm_kho_folios_ser {
+ u64 nr_folios;
+ u64 folios_pa[];
+} __packed;
+
+/**
+ * struct kvm_caretaker_cb_ser - KVM Caretaker Control Block
+ * @state: Current Caretaker execution state (enum kvm_caretaker_state).
+ * @pcpu_id: Physical CPU ID where this vCPU runs while in Caretaker.
+ * @vcpu_id: Guest vCPU identifier.
+ * @reserved: Must be zero.
+ * @telemetry: Preservation pointer to Caretaker execution telemetry.
+ *
+ * Coordinates vCPU execution state across hypervisor detachment,
+ * live update, and Caretaker CPU preservation.
+ */
+struct kvm_caretaker_cb_ser {
+ u32 state;
+ u32 pcpu_id;
+ u32 vcpu_id;
+ u32 reserved;
+ DECLARE_KHOSER_PTR(telemetry, struct kvm_caretaker_telemetry_ser *);
+} __packed;
+
/**
* struct kvm_vcpu_ser - Main serialization structure for a KVM vCPU.
* @vcpu_id: The ID of the virtual CPU.
* @flags: Flags for vCPU preservation.
* @vm_token: Token of the associated KVM VM instance.
* @arch_state: Preservation pointer to vCPU architectural state.
+ * @cb: Preservation pointer to Caretaker Control Block.
+ *
+ * Cross-kexec invariant: the incoming kernel may only dereference structures
+ * declared in include/linux/kho/abi/ headers. When @flags includes
+ * %KVM_VCPU_LUO_FLAG_CARETAKER, the preserved Caretaker text writes live guest
+ * state into @arch_state at detach time before transitioning @cb to
+ * %KVM_CARETAKER_STOPPED; the incoming kernel reads only @cb and @arch_state.
*/
struct kvm_vcpu_ser {
u32 vcpu_id;
u32 flags;
u64 vm_token;
DECLARE_KHOSER_PTR(arch_state, struct kvm_vcpu_arch_ser *);
+ DECLARE_KHOSER_PTR(cb, struct kvm_caretaker_cb_ser *);
} __packed;
/* The compatibility string for KVM vCPU file handler */
diff --git a/include/linux/kvm_caretaker.h b/include/linux/kvm_caretaker.h
new file mode 100644
index 000000000000..3e89738d7fdf
--- /dev/null
+++ b/include/linux/kvm_caretaker.h
@@ -0,0 +1,341 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2026, Google LLC.
+ * Pasha Tatashin <pasha.tatashin@xxxxxxxxxx>
+ *
+ * Header for common KVM Caretaker framework across architectures.
+ */
+#ifndef __LINUX_KVM_CARETAKER_H
+#define __LINUX_KVM_CARETAKER_H
+
+#include <linux/types.h>
+#include <linux/kho/abi/kvm.h>
+
+struct kvm_vcpu;
+struct kvm_vcpu_ser;
+struct liveupdate_session;
+
+/**
+ * enum kvm_caretaker_exit_type - Normalized cross-architecture VM exit classification
+ * @KVM_CARETAKER_EXIT_UNKNOWN: Unclassified exit; treated as unhandled stall.
+ * @KVM_CARETAKER_EXIT_IDLE: Guest idle instruction (HLT, PAUSE, WFI, WFE).
+ * @KVM_CARETAKER_EXIT_CONSOLE: Early console port I/O or MMIO access.
+ * @KVM_CARETAKER_EXIT_PREEMPT_TIMER: Hardware quantum preemption timer expired.
+ * @KVM_CARETAKER_EXIT_CROSS_VCPU: Cross-vCPU notification or IPI (e.g., SGI).
+ * @KVM_CARETAKER_EXIT_INSN_STEP: Instruction emulated by decode; advance RIP/PC.
+ * @KVM_CARETAKER_EXIT_ARCH: Architecture-specific exit routed to @handle_arch_exit.
+ * @KVM_CARETAKER_EXIT_UNHANDLED: Exit requiring full KVM/VMM; stalls the vCPU.
+ */
+enum kvm_caretaker_exit_type {
+ KVM_CARETAKER_EXIT_UNKNOWN = 0,
+ KVM_CARETAKER_EXIT_IDLE,
+ KVM_CARETAKER_EXIT_CONSOLE,
+ KVM_CARETAKER_EXIT_PREEMPT_TIMER,
+ KVM_CARETAKER_EXIT_CROSS_VCPU,
+ KVM_CARETAKER_EXIT_INSN_STEP,
+ KVM_CARETAKER_EXIT_ARCH,
+ KVM_CARETAKER_EXIT_UNHANDLED,
+};
+
+/**
+ * struct kvm_caretaker_exit - Normalized cross-architecture VM exit representation
+ * @type: Normalized exit classification (&enum kvm_caretaker_exit_type).
+ * @rip: Guest instruction pointer (RIP on x86, PC on arm64) at exit.
+ * @insn_len: Length in bytes of the trapping instruction.
+ * @raw_reason: Raw hardware exit code (VMX exit reason, SVM exit code, or ESR_EL2).
+ * @mmio_io: Decoded port I/O or MMIO access parameters.
+ * @msr: Decoded x86 MSR read/write parameters.
+ * @sgi: Decoded arm64 GICv3 Software Generated Interrupt parameters.
+ */
+struct kvm_caretaker_exit {
+ enum kvm_caretaker_exit_type type;
+ u64 rip;
+ u32 insn_len;
+ u64 raw_reason;
+ union {
+ struct {
+ u64 addr;
+ u64 val;
+ u64 *val_ptr;
+ u32 size;
+ bool is_write;
+ bool is_mmio;
+ } mmio_io;
+ struct {
+ u32 msr;
+ u64 val;
+ bool is_write;
+ } msr;
+ struct {
+ u32 sgi_id;
+ u64 target_mask;
+ } sgi;
+ };
+};
+
+struct kvm_caretaker_vcpu;
+
+/**
+ * struct kvm_caretaker_ops - Architecture operations vector for Caretaker vCPU execution
+ * @enter_guest: Perform low-level hardware guest entry (VMLAUNCH/VMRESUME,
+ * VMRUN, or EL2 ERET). Returns 0 on guest exit, or non-zero
+ * on entry failure.
+ * @decode_exit: Read hardware exit registers and populate @exit.
+ * @handle_arch_exit: Emulate an architecture-specific exit (@exit). Returns
+ * %true if handled (and updates @exit->rip if needed), or
+ * %false to stall the vCPU until the incoming kernel attaches.
+ * @advance_rip: Write updated @next_rip back into hardware guest state.
+ * @arm_timer: Program hardware preemption timer to fire at @deadline_ticks
+ * (or disarm if @deadline_ticks is 0).
+ * @disarm_timer: Disarm the hardware preemption timer after leaving the loop.
+ * @pre_run: Optional per-quantum setup hook invoked before guest entry.
+ * @post_run: Optional per-quantum teardown hook invoked after leaving
+ * the guest loop.
+ */
+struct kvm_caretaker_ops {
+ int (*enter_guest)(void *vcpu_data);
+ void (*decode_exit)(void *vcpu_data, struct kvm_caretaker_exit *exit);
+ bool (*handle_arch_exit)(void *vcpu_data, struct kvm_caretaker_exit *exit);
+ void (*advance_rip)(void *vcpu_data, u64 next_rip);
+ void (*arm_timer)(void *vcpu_data, u64 deadline_ticks);
+ void (*disarm_timer)(void *vcpu_data);
+ void (*pre_run)(void *vcpu_data);
+ void (*post_run)(void *vcpu_data);
+};
+
+/**
+ * struct kvm_caretaker_vcpu - Common per-vCPU Caretaker runtime descriptor
+ * @cb: Pointer to KHO-preserved Caretaker control block (&struct kvm_caretaker_cb_ser).
+ * @ops: Architecture operations vector (&struct kvm_caretaker_ops).
+ * @arch_data: Architecture-specific runtime context passed to @ops callbacks.
+ */
+struct kvm_caretaker_vcpu {
+ struct kvm_caretaker_cb_ser *cb;
+ const struct kvm_caretaker_ops *ops;
+ void *arch_data;
+};
+
+struct kvm_kho_folios_ser *kvm_kho_folios_alloc(unsigned int max_folios);
+void kvm_kho_folios_unpreserve(struct kvm_kho_folios_ser *folios);
+void kvm_kho_folios_finish(struct kvm_kho_folios_ser *folios);
+
+#ifdef CONFIG_KVM_CARETAKER
+
+#include <linux/cpu_preserve.h>
+#include <linux/oncore.h>
+
+#define __caretaker_text __cpu_preserved_text
+#define __caretaker_data __cpu_preserved_data
+
+struct dentry;
+struct oncore_session;
+
+/**
+ * struct kvm_vcpu_caretaker - Host-side Caretaker state embedded in struct kvm_vcpu
+ * @cb: Pointer to the KHO-preserved Caretaker control block while
+ * preserved, or %NULL when executing normally under KVM.
+ * @job: On-Core scheduler job handle for this vCPU, or %NULL.
+ * @last_telemetry: Snapshot of @cb->telemetry captured upon re-attachment.
+ */
+struct kvm_vcpu_caretaker {
+ struct kvm_caretaker_cb_ser *cb;
+ struct oncore_job *job;
+ struct kvm_caretaker_telemetry_ser last_telemetry;
+};
+
+/**
+ * kvm_caretaker_is_stopped - Check whether a Caretaker control block is stopped
+ * @cb: Caretaker control block (may be %NULL).
+ *
+ * Return: %true if @cb is %NULL or in state %KVM_CARETAKER_STOPPED, %false otherwise.
+ */
+static inline bool kvm_caretaker_is_stopped(const struct kvm_caretaker_cb_ser *cb)
+{
+ return !cb || smp_load_acquire(&cb->state) == KVM_CARETAKER_STOPPED;
+}
+
+/**
+ * kvm_caretaker_pause - Transition a Caretaker control block to PAUSED state
+ * @cb: Caretaker control block.
+ *
+ * Publishes %KVM_CARETAKER_PAUSED with release semantics so a preserved CPU
+ * can claim the vCPU for on-core execution.
+ */
+static inline void kvm_caretaker_pause(struct kvm_caretaker_cb_ser *cb)
+{
+ /* Pairs with smp_load_acquire() in caretaker loop */
+ smp_store_release(&cb->state, KVM_CARETAKER_PAUSED);
+}
+
+/**
+ * kvm_caretaker_stop - Transition a Caretaker control block to STOPPED state
+ * @cb: Caretaker control block.
+ *
+ * Publishes %KVM_CARETAKER_STOPPED with release semantics once the vCPU has
+ * detached from Caretaker execution.
+ */
+static inline void kvm_caretaker_stop(struct kvm_caretaker_cb_ser *cb)
+{
+ /* Pairs with smp_load_acquire() in caretaker loop */
+ smp_store_release(&cb->state, KVM_CARETAKER_STOPPED);
+}
+
+bool kvm_caretaker_vcpu_is_attached(struct kvm_vcpu *vcpu);
+void kvm_caretaker_init_common_vcpu(struct kvm_caretaker_vcpu *cvcpu,
+ struct kvm_caretaker_cb_ser *cb,
+ struct kvm_vcpu *vcpu,
+ void *runtime_va,
+ size_t runtime_size,
+ const struct kvm_caretaker_ops *ops,
+ void *arch_data);
+bool kvm_caretaker_should_exit(struct kvm_caretaker_vcpu *cvcpu);
+enum oncore_exit_reason
+kvm_caretaker_vcpu_run(struct kvm_caretaker_vcpu *cvcpu, u64 deadline_ticks);
+int kvm_caretaker_wait_for_attach(struct kvm_caretaker_cb_ser *cb, int pcpu);
+void kvm_caretaker_post_attach_vcpu(struct kvm_vcpu *vcpu);
+
+/**
+ * kvm_arch_vcpu_caretaker_run - Architecture entry point for Caretaker vCPU run
+ * @data: Pointer to KHO-preserved Caretaker control block
+ * (&struct kvm_caretaker_cb_ser) embedded in the architecture
+ * runtime page.
+ * @deadline_ticks: Hardware counter deadline (TSC on x86, CNTPCT on arm64) at
+ * which the current scheduling quantum expires, or 0 if
+ * unbounded.
+ *
+ * Invoked by the On-Core scheduler loop on a preserved physical CPU during the
+ * kexec handover window. Atomically transitions the vCPU from
+ * %KVM_CARETAKER_PAUSED to %KVM_CARETAKER_RUNNING, switches to Caretaker host
+ * state and isolated page tables, invokes kvm_caretaker_vcpu_run(), and
+ * serializes updated guest registers back to KHO memory upon exit.
+ *
+ * Context: Runs in __cpu_preserved_text with local interrupts disabled.
+ * Return: &enum oncore_exit_reason indicating why the vCPU yielded the core.
+ */
+enum oncore_exit_reason
+kvm_arch_vcpu_caretaker_run(void *data, u64 deadline_ticks);
+
+/**
+ * kvm_arch_vcpu_luo_pre_retrieve_caretaker - Signal Caretaker vCPU to stop and serialize
+ * @vcpu: Incoming or cancelled-handover KVM vCPU structure.
+ * @ser: Serialized KHO vCPU metadata.
+ *
+ * Signals the preserved physical CPU executing this vCPU in Caretaker to exit
+ * guest mode, serialize live guest hardware state into @ser->arch_state, and
+ * transition to %KVM_CARETAKER_STOPPED. Must run before
+ * kvm_arch_vcpu_luo_retrieve() reads @ser->arch_state.
+ */
+void kvm_arch_vcpu_luo_pre_retrieve_caretaker(struct kvm_vcpu *vcpu,
+ struct kvm_vcpu_ser *ser);
+
+/**
+ * kvm_arch_vcpu_luo_attach_caretaker - Complete architecture vCPU attachment after retrieve
+ * @vcpu: Incoming kernel vCPU structure being restored.
+ * @ser: Serialized KHO vCPU metadata containing the Caretaker control block PA.
+ *
+ * Runs after kvm_arch_vcpu_luo_retrieve() has restored @ser->arch_state into
+ * @vcpu; synchronizes architecture-specific hardware state (VMCS/VMCB/VGIC and
+ * emulated UART/timer state) from the preserved Caretaker page and completes
+ * attachment via kvm_caretaker_post_attach_vcpu().
+ */
+void kvm_arch_vcpu_luo_attach_caretaker(struct kvm_vcpu *vcpu,
+ struct kvm_vcpu_ser *ser);
+
+int kvm_caretaker_vcpu_pre_preserve(struct kvm_vcpu *vcpu,
+ struct liveupdate_session *session,
+ struct kvm_vcpu_ser *ser);
+int kvm_caretaker_vcpu_post_preserve(struct kvm_vcpu *vcpu,
+ struct liveupdate_session *session,
+ struct kvm_vcpu_ser *ser,
+ int arch_err);
+void kvm_caretaker_vcpu_pre_retrieve(struct kvm_vcpu *vcpu,
+ struct kvm_vcpu_ser *ser);
+void kvm_caretaker_vcpu_retrieve(struct kvm_vcpu *vcpu,
+ struct kvm_vcpu_ser *ser);
+void kvm_caretaker_vcpu_unpreserve(struct kvm_vcpu *vcpu,
+ struct liveupdate_session *session,
+ struct kvm_vcpu_ser *ser);
+void kvm_caretaker_vcpu_finish(struct kvm_vcpu *vcpu,
+ struct liveupdate_session *session,
+ struct kvm_vcpu_ser *ser);
+
+#else /* !CONFIG_KVM_CARETAKER */
+
+#define __caretaker_text
+#define __caretaker_data
+
+static inline bool kvm_caretaker_is_stopped(const struct kvm_caretaker_cb_ser *cb)
+{
+ return true;
+}
+
+static inline void kvm_caretaker_pause(struct kvm_caretaker_cb_ser *cb) {}
+
+static inline void kvm_caretaker_stop(struct kvm_caretaker_cb_ser *cb) {}
+
+static inline bool kvm_caretaker_vcpu_is_attached(struct kvm_vcpu *vcpu)
+{
+ return true;
+}
+
+static inline void kvm_caretaker_vm_pre_retrieve(void) {}
+
+static inline int kvm_caretaker_vcpu_pre_preserve(struct kvm_vcpu *vcpu,
+ struct liveupdate_session *session,
+ struct kvm_vcpu_ser *ser)
+{
+ return 0;
+}
+
+static inline int kvm_caretaker_vcpu_post_preserve(struct kvm_vcpu *vcpu,
+ struct liveupdate_session *session,
+ struct kvm_vcpu_ser *ser,
+ int arch_err)
+{
+ return arch_err;
+}
+
+static inline void kvm_caretaker_init_common_vcpu(struct kvm_caretaker_vcpu *cvcpu,
+ struct kvm_caretaker_cb_ser *cb,
+ struct kvm_vcpu *vcpu,
+ void *runtime_va,
+ size_t runtime_size,
+ const struct kvm_caretaker_ops *ops,
+ void *arch_data) {}
+
+static inline bool kvm_caretaker_should_exit(struct kvm_caretaker_vcpu *cvcpu)
+{
+ return true;
+}
+
+static inline int kvm_caretaker_wait_for_attach(struct kvm_caretaker_cb_ser *cb, int pcpu,
+ void (*arch_kick)(int pcpu))
+{
+ return 0;
+}
+
+static inline void kvm_caretaker_post_attach_vcpu(struct kvm_vcpu *vcpu) {}
+
+static inline void kvm_arch_vcpu_luo_pre_retrieve_caretaker(struct kvm_vcpu *vcpu,
+ struct kvm_vcpu_ser *ser) {}
+
+static inline void kvm_arch_vcpu_luo_attach_caretaker(struct kvm_vcpu *vcpu,
+ struct kvm_vcpu_ser *ser) {}
+
+static inline void kvm_caretaker_vcpu_pre_retrieve(struct kvm_vcpu *vcpu,
+ struct kvm_vcpu_ser *ser) {}
+
+static inline void kvm_caretaker_vcpu_retrieve(struct kvm_vcpu *vcpu,
+ struct kvm_vcpu_ser *ser) {}
+
+static inline void kvm_caretaker_vcpu_unpreserve(struct kvm_vcpu *vcpu,
+ struct liveupdate_session *session,
+ struct kvm_vcpu_ser *ser) {}
+
+static inline void kvm_caretaker_vcpu_finish(struct kvm_vcpu *vcpu,
+ struct liveupdate_session *session,
+ struct kvm_vcpu_ser *ser) {}
+
+#endif /* CONFIG_KVM_CARETAKER */
+
+#endif /* __LINUX_KVM_CARETAKER_H */
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 643b941286c2..aca3c41346fb 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -44,6 +44,7 @@
#include <asm/kvm_host.h>
#include <linux/kvm_dirty_ring.h>
+#include <linux/kvm_caretaker.h>
#ifndef KVM_MAX_VCPU_IDS
#define KVM_MAX_VCPU_IDS KVM_MAX_VCPUS
@@ -398,6 +399,9 @@ struct kvm_vcpu {
*/
struct kvm_memory_slot *last_used_slot;
u64 last_used_slot_gen;
+#ifdef CONFIG_KVM_CARETAKER
+ struct kvm_vcpu_caretaker caretaker;
+#endif
};
/*
@@ -887,6 +891,12 @@ struct kvm {
* RCU (e.g. via get_file_active() to prevent ABA races).
*/
struct file __rcu *vm_file;
+#endif
+#ifdef CONFIG_LIVEUPDATE
+ struct kvm_kho_folios_ser *kho_folios;
+#endif
+#ifdef CONFIG_KVM_CARETAKER
+ void *caretaker_vm;
#endif
char stats_id[KVM_STATS_NAME_SIZE];
};
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 4b1754050681..1042cff30fef 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -1000,6 +1000,7 @@ struct kvm_enable_cap {
#define KVM_CAP_PPC_COMPAT_CAPS 250
#define KVM_CAP_ARM_PMU_V3_STRICT 251
#define KVM_CAP_VCPU_PRESERVE 252
+#define KVM_CAP_CARETAKER 253
struct kvm_irq_routing_irqchip {
__u32 irqchip;
--
2.55.0.1082.g2b9226bbc0-goog