mbox series

[RFC,0/7] KSTATE: a mechanism to migrate some part of the kernel state across kexec

Message ID 20241002160722.20025-1-arbn@yandex-team.com (mailing list archive)
Headers show
Series KSTATE: a mechanism to migrate some part of the kernel state across kexec | expand

Message

Andrey Ryabinin Oct. 2, 2024, 4:07 p.m. UTC
kstate (kernel state) is a mechanism to describe internal some part of the
kernel state, save it into the memory and restore the state after kexec
in the new kernel.

This is a very early RFC with a lot of hacks and cut corners with
the purpose to demonstrate the concept itself. Some parts
of this feature isn't well thought trough yet (like dealing with
struct changes between old and new kernel, fixed size of migrate stream
memory and absence of boundary checks, and so on and on).

The end goal here and the main use case for this is to be able to
update host kernel under VMs with VFIO pass-through devices running
on that host.
We are pretty far from that end goal yet. This patchset only tries
to establish some basic infrastructure to describe and migrate complex
in-kernel states.

The inspiration for this came from QEMU and its VMSTATE stuff which
is used to solve similar problem - migrate complex internal state
across different versions of QEMU. So there is a bit of similarity here.

The alternative for the kstate is KHO (Kexec Hand Over) [1].
Since in KHO migrates trace buffers, I decided to choose them
as a victim for kstate too. So we can compare both approaches.

In my very biased opinion with kstate it's much easier to describe
some state to migrate it to new kernel. And seems requires
almost none intervention into existing code paths of the subsystem.icated


So now to the part how this works.

States (usually this is some struct) are described by the
'struct kstate_description' containing the array of individual
fields descpriptions - 'struct kstate_field'.
Fields have different types like:
   KS_SIMPLE  - trivial type that just copied by value

   KS_POINTER - field contains pointer, it will be dereferenced to copy
     the value during save/restore phases.

   KS_STRUCT - contains another struct,
       field->ksd must point to another 'struct kstate_dscription'

   KS_CUSTOM - something that requires fit trivial types as above,
               for this fields the callbacks field->save()/->restore() must
	       do all job
   KS_ARRAY_OF_POINTER - array of pointers, the size of array determined by the
                         field->count() callback
   KS_END - special flag indicating the end of migration stream data.


kstate_register() call accepts kstate_description along with an instance
of an object and registers it in the global 'states' list.

During kexec reboot phase this list iterated, and for each instance
in the list 'struct kstate_entry' formed and saved in the migration stream.
'kstate_entry' contains information like ID of kstate_description, version
of it, size of migration data and the data itself.

After the reboot, when the kstate_register() called it parses migration
stream, finds the appropriate 'kstate_entry' and restores the contents of the
object.

The content of this patchset:

The first patch contains the most of the basic KSTATE infrastructure.

The 2,3 patches are temporary hacks needed to pass the memory used to store
migration data across kexec. Will be completely redone later.

The 4,5 patches are bits needed to preserve pages intact across kexec.

6 is test&playground patch to develop and test kstate itself.

7 is a demonstration of how to migrate trace buffer using kstate.


[1] https://lore.kernel.org/all/20240117144704.602-1-graf@amazon.com/

Andrey Ryabinin (7):
  kstate: Add kstate - a mechanism to migrate some kernel state across
    kexec
  kexec: Hack and abuse crashkernel for the kstate's migration stream
  [hack] purgatory: disable purgatory verification.
  mm/memblock: Add MEMBLOCK_PRSRV flag
  kstate: Add mechanism to preserved specified memory pages across
    kexec.
  kstate, test: add test module for testing kstate subsystem.
  trace: migrate trace buffers across kexec

 arch/x86/kernel/kexec-bzimage64.c  |  36 +++++
 arch/x86/kernel/machine_kexec_64.c |   5 +-
 arch/x86/kernel/setup.c            |  81 ++++++++++++
 arch/x86/purgatory/purgatory.c     |   2 +
 include/linux/kexec.h              |   6 +-
 include/linux/kstate.h             | 129 ++++++++++++++++++
 include/linux/memblock.h           |   7 +
 include/uapi/linux/kexec.h         |   2 +
 kernel/Kconfig.kexec               |  12 ++
 kernel/Makefile                    |   1 +
 kernel/crash_core.c                |   3 +-
 kernel/kexec_core.c                |  10 +-
 kernel/kexec_file.c                |  15 ++-
 kernel/kstate.c                    | 205 +++++++++++++++++++++++++++++
 kernel/trace/ring_buffer.c         | 189 ++++++++++++++++++++++++++
 kernel/trace/trace.c               |  81 ++++++++++++
 lib/Makefile                       |   2 +
 lib/test_kstate.c                  |  89 +++++++++++++
 mm/memblock.c                      |   9 +-
 mm/mm_init.c                       |  19 +++
 20 files changed, 895 insertions(+), 8 deletions(-)
 create mode 100644 include/linux/kstate.h
 create mode 100644 kernel/kstate.c
 create mode 100644 lib/test_kstate.c