Skip to content

Create communication channel between two SVSM#23

Open
ruzickajakub wants to merge 41 commits intococonut-svsm:svsm-igvmfrom
ruzickajakub:create-communication-channel
Open

Create communication channel between two SVSM#23
ruzickajakub wants to merge 41 commits intococonut-svsm:svsm-igvmfrom
ruzickajakub:create-communication-channel

Conversation

@ruzickajakub
Copy link

@ruzickajakub ruzickajakub commented Jun 27, 2025

This proof of concept introduces two new commands, snp_migrate <uri> <address> and snp_migrate_incoming <uri> <address>, that together create a communication channel over which the SVSM instances can send the migration data.

The first argument specifies the communication channel. Currently, only sockets are supported. The migration data and commands are read from migration page, which is a single shared page, whose address is provided as a second argument.

Migration page has the following structure:

--------------------------------------------------------------------------
Offset    Size     Name                Notes
--------------------------------------------------------------------------
0x0        0x1      status register     Used to communicate the current
                                                  status of migration: not started,
                                                  incoming, running, completed.
0x1        0x1      data register       Used to communicate data
                                                 availability: data ready, data
                                                 read.
0x2        0x7FD  reserved
0x800    0x800   data buffer         Used for data transfer between QEMU
                                     and SVSM.
--------------------------------------------------------------------------

The hypervisor is deemed untrusted in a confidential computing scenario. Therefore, the only thing we want from the hypervisor is to provide a communication channel over which the SVSM instances can communicate without implementing the network stack. This patch should accomplish just that. The rest of the work should be done in the SVSM.

roy-hopkins and others added 30 commits September 26, 2024 09:29
The IGVM library allows Independent Guest Virtual Machine files to be
parsed and processed. IGVM files are used to configure guest memory
layout, initial processor state and other configuration pertaining to
secure virtual machines.

This adds the --enable-igvm configure option, enabled by default, which
attempts to locate and link against the IGVM library via pkgconfig and
sets CONFIG_IGVM if found.

The library is added to the system_ss target in backends/meson.build
where the IGVM parsing will be performed by the ConfidentialGuestSupport
object.

Signed-off-by: Roy Hopkins <[email protected]>
Acked-by: Michael S. Tsirkin <[email protected]>
Reviewed-by: Daniel P. Berrangé <[email protected]>
Reviewed-by: Stefano Garzarella <[email protected]>
In preparation for supporting the processing of IGVM files to configure
guests, this adds a set of functions to ConfidentialGuestSupport
allowing configuration of secure virtual machines that can be
implemented for each supported isolation platform type such as Intel TDX
or AMD SEV-SNP. These functions will be called by IGVM processing code
in subsequent patches.

This commit provides a default implementation of the functions that
either perform no action or generate an error when they are called.
Targets that support ConfidentalGuestSupport should override these
implementations.

Signed-off-by: Roy Hopkins <[email protected]>
Acked-by: Michael S. Tsirkin <[email protected]>
Reviewed-by: Stefano Garzarella <[email protected]>
Adds an IGVM loader to QEMU which processes a given IGVM file and
applies the directives within the file to the current guest
configuration.

The IGVM loader can be used to configure both confidential and
non-confidential guests. For confidential guests, the
ConfidentialGuestSupport object for the system is used to encrypt
memory, apply the initial CPU state and perform other confidential guest
operations.

The loader is configured via a new IgvmCfg QOM object which allows the
user to provide a path to the IGVM file to process.

Signed-off-by: Roy Hopkins <[email protected]>
Acked-by: Michael S. Tsirkin <[email protected]>
Reviewed-by: Stefano Garzarella <[email protected]>
An IGVM file contains configuration of guest state that should be
applied during configuration of the guest, before the guest is started.

This patch allows the user to add an igvm-cfg object to an X86 machine
configuration that allows an IGVM file to be configured that will be
applied to the guest before it is started.

If an IGVM configuration is provided then the IGVM file is processed at
the end of the board initialization, before the state transition to
PHASE_MACHINE_INITIALIZED.

Signed-off-by: Roy Hopkins <[email protected]>
Reviewed-by: Michael S. Tsirkin <[email protected]>
…h IGVM

When using an IGVM file the configuration of the system firmware is
defined by IGVM directives contained in the file. In this case the user
should not configure any pflash devices.

This commit skips initialization of the ROM mode when pflash0 is not set
then checks to ensure no pflash devices have been configured when using
IGVM, exiting with an error message if this is not the case.

Signed-off-by: Roy Hopkins <[email protected]>
Reviewed-by: Daniel P. Berrangé <[email protected]>
Reviewed-by: Michael S. Tsirkin <[email protected]>
Reviewed-by: Stefano Garzarella <[email protected]>
The class function and implementations for updating launch data return
a code in case of error. In some cases an error message is generated and
in other cases, just the error return value is used.

This small refactor adds an 'Error **errp' parameter to all functions
which consistently set an error condition if a non-zero value is
returned.

Signed-off-by: Roy Hopkins <[email protected]>
Acked-by: Michael S. Tsirkin <[email protected]>
Reviewed-by: Pankaj Gupta <[email protected]>
Reviewed-by: Stefano Garzarella <[email protected]>
…ache()

The x86 segment registers are identified by the X86Seg enumeration which
includes LDTR and TR as well as the normal segment registers. The
function 'cpu_x86_load_seg_cache()' uses the enum to determine which
segment to set. However, specifying R_LDTR or R_TR results in an
out-of-bounds access of the segment array.

Possibly by coincidence, the function does correctly set LDTR or TR in
this case as the structures for these registers immediately follow the
array which is accessed out of bounds.

This patch adds correct handling for R_LDTR and R_TR in the function.

Signed-off-by: Roy Hopkins <[email protected]>
Reviewed-by: Michael S. Tsirkin <[email protected]>
Reviewed-by: Stefano Garzarella <[email protected]>
When an SEV guest is started, the reset vector and state are
extracted from metadata that is contained in the firmware volume.

In preparation for using IGVM to setup the initial CPU state,
the code has been refactored to populate vmcb_save_area for each
CPU which is then applied during guest startup and CPU reset.

Signed-off-by: Roy Hopkins <[email protected]>
Acked-by: Michael S. Tsirkin <[email protected]>
Acked-by: Stefano Garzarella <[email protected]>
The ConfidentialGuestSupport object defines a number of virtual
functions that are called during processing of IGVM directives to query
or configure initial guest state. In order to support processing of IGVM
files, these functions need to be implemented by relevant isolation
hardware support code such as SEV.

This commit implements the required functions for SEV-ES and adds
support for processing IGVM files for configuring the guest.

Signed-off-by: Roy Hopkins <[email protected]>
Acked-by: Michael S. Tsirkin <[email protected]>
Acked-by: Stefano Garzarella <[email protected]>
IGVM support has been implemented for Confidential Guests that support
AMD SEV and AMD SEV-ES. Add some documentation that gives some
background on the IGVM format and how to use it to configure a
confidential guest.

Signed-off-by: Roy Hopkins <[email protected]>
Reviewed-by: Daniel P. Berrangé <[email protected]>
Reviewed-by: Stefano Garzarella <[email protected]>
Acked-by: Michael S. Tsirkin <[email protected]>
Create an enum entry within FirmwareDevice for 'igvm' to describe that
an IGVM file can be used to map firmware into memory as an alternative
to pre-existing firmware devices.

Signed-off-by: Roy Hopkins <[email protected]>
Acked-by: Michael S. Tsirkin <[email protected]>
Reviewed-by: Stefano Garzarella <[email protected]>
For confidential guests a policy can be provided that defines the
security level, debug status, expected launch measurement and other
parameters that define the configuration of the confidential platform.

This commit adds a new function named set_guest_policy() that can be
implemented by each confidential platform, such as AMD SEV to set the
policy. This will allow configuration of the policy from a
multi-platform resource such as an IGVM file without the IGVM processor
requiring specific implementation details for each platform.

Signed-off-by: Roy Hopkins <[email protected]>
Reviewed-by: Daniel P. Berrangé <[email protected]>
Reviewed-by: Stefano Garzarella <[email protected]>
Acked-by: Michael S. Tsirkin <[email protected]>
The initialization sections in IGVM files contain configuration that
should be applied to the guest platform before it is started. This
includes guest policy and other information that can affect the security
level and the startup measurement of a guest.

This commit introduces handling of the initialization sections during
processing of the IGVM file.

Signed-off-by: Roy Hopkins <[email protected]>
Acked-by: Michael S. Tsirkin <[email protected]>
Reviewed-by: Stefano Garzarella <[email protected]>
Adds a handler for the guest policy initialization IGVM section and
builds an SEV policy based on this information and the ID block
directive if present. The policy is applied using by calling
'set_guest_policy()' on the ConfidentialGuestSupport object.

Signed-off-by: Roy Hopkins <[email protected]>
Acked-by: Michael S. Tsirkin <[email protected]>
Acked-by: Stefano Garzarella <[email protected]>
The new cgs_set_guest_policy() function is provided to receive the guest
policy flags, SNP ID block and SNP ID authentication from guest
configuration such as an IGVM file and apply it to the platform prior to
launching the guest.

The policy is used to populate values for the existing 'policy',
'id_block' and 'id_auth' parameters. When provided, the guest policy is
applied and the ID block configuration is used to verify the launch
measurement and signatures. The guest is only successfully started if
the expected launch measurements match the actual measurements and the
signatures are valid.

Signed-off-by: Roy Hopkins <[email protected]>
Acked-by: Michael S. Tsirkin <[email protected]>
Acked-by: Stefano Garzarella <[email protected]>
IGVM files can contain an initial VMSA that should be applied to each
vcpu as part of the initial guest state. The sev_features flags are
provided as part of the VMSA structure. However, KVM only allows
sev_features to be set during initialization and not as the guest is
being prepared for launch.

This patch queries KVM for the supported set of sev_features flags and
processes the IGVM file during kvm_init to determine any sev_features
flags set in the IGVM file. These are then provided in the call to
KVM_SEV_INIT2 to ensure the guest state matches that specified in the
IGVM file.

This does cause the IGVM file to be processed twice. Firstly to extract
the sev_features then secondly to actually configure the guest. However,
the first pass is largely ignored meaning the overhead is minimal.

Signed-off-by: Roy Hopkins <[email protected]>
Acked-by: Michael S. Tsirkin <[email protected]>
Acked-by: Stefano Garzarella <[email protected]>
Previously the VMSA could not be set directly. Instead the current CPU
state was automatically populated into a VMSA within kvm as part of
KVM_SEV_SNP_LAUNCH_FINISH. This meant that it was hard to ensure the
VMSA provided by IGVM matched the resulting one in kvm.

KVM has been updated to allow the VMSA to be provided via
KVM_SEV_SNP_LAUNCH_UPDATE. In this case, kvm does not perform any
specific synchronisation during FINISH and the VMSA is guaranteed to
match that provided by QEMU.

Signed-off-by: Roy Hopkins <[email protected]>
Implement a ConfidentialGuestSupportClass for non-confidential VMs.
This allows the igvm support code work without sev.

TODO: Not fully sure this is the best way to implement this.
Alternatively we could add this directly into the igvm code.

TODO: Hooking the register state load into vcpu reset is hacky.

TODO: Add proper reset (init memory too, not only registers).

Usage:
  qemu-system-x86_64 \
    -object nocc,id=nocc0 \
    -machine confidential-guest-support=nocc0

Signed-off-by: Gerd Hoffmann <[email protected]>
load state from igvm for non-cc VMs
igvm spec says in case the igvm image does not contain a
NativeVpContextX64 directive registers should be initialized to
architectural reset state.

qemu zero-fills the registers instead.  Fix that by tracking and
checking whenever we actually got the initial cpu register state.

Signed-off-by: Gerd Hoffmann <[email protected]>
The additional read of the ACPI tables in SVSM throws something off in
Qemu and as a result Linux will not boot without errors or at all.

See coconut-svsm/svsm#646

Signed-off-by: Joerg Roedel <[email protected]>
(cherry picked from commit 133da2c)
Signed-off-by: Oliver Steffen <[email protected]>
ACPI: Rebuild ACPI tables on every read
This is a temporary workaround to avoid a build problem with qemu-user
since nocc.c depends on confidential-guest.c.

In the long run we will reorganize the code to avoid the dependency and
compile nocc.c without CONFIG_SEV.

Reported-by: Luigi Leonardi <[email protected]>
Closes: coconut-svsm/svsm#665
Fixes: 06c0498 ("load state from igvm for non-cc VMs")
Signed-off-by: Stefano Garzarella <[email protected]>
Update the code in net/slirp.c to be compatible with
libslirp 4.9.0, which deprecated slirp_pollfds_fill()
and started using slirp_os_socket type for sockets
(which is a 64-bit integer on win64) for all callbacks
starting with version 6 of the interface.

Signed-off-by: Michael Tokarev <[email protected]>
Reviewed-by: Samuel Thibault <[email protected]>
Message-ID: <[email protected]>
[thuth: Added some spaces to make checkpatch.pl happy]
Signed-off-by: Thomas Huth <[email protected]>
net/slirp: libslirp 4.9.0 compatibility
Disabled by default, enable using '-machine q35,x-svsm-virtio-mmio=on'.

When enabled it is possible to plug up to 4 virtio devices into the
slots virtio-mmio using '-device virtio-${kind}-device'.

The devices can be found at base address 0xfef00000, each slot on a
separate page.  No IRQ is wired up, the svsm has to drive the devices
in polling mode.

Signed-off-by: Gerd Hoffmann <[email protected]>
edk2 looks for the etc/hardware-info fw_cfg file to discover hardware
which can not easily be found in other ways.  Entries consist of a
header with hardware type and entry size (HARDWARE_INFO_HEADER),
followed by the actual hardware description (which is type specific).
The file can have multiple entries.

This patch adds the infrastructure to add entries to the file and an
entry struct for simple devices (HARDWARE_INFO_SIMPLE_DEVICE) which have
an mmio address only.

Signed-off-by: Gerd Hoffmann <[email protected]>
Signed-off-by: Gerd Hoffmann <[email protected]>
kraxel and others added 7 commits April 24, 2025 13:34
igvm spec says in case the igvm image does not contain a
NativeVpContextX64 directive registers should be initialized to
architectural reset state.

qemu zero-fills the registers instead.  Fix that by tracking and
checking whenever we actually got the initial cpu register state.

Signed-off-by: Gerd Hoffmann <[email protected]>
fixes for nocc (native igvm)
nocc: build it only when CONFIG_SEV is defined
This proof of concept introduces two new commands, `snp_migrate <uri>
<address>` and `snp_migrate_incoming <uri> <address>`, that together
create a communication channel over which the SVSM instances can send
the migration data.

The first argument specifies the communication channel. Currently, only
sockets are supported. The migration data and commands are read from
migration page, which is a single shared page, whose address is provided
as a second argument.

Migration page has the following structure:
--------------------------------------------------------------------------
Offset   Size    Name                Notes
--------------------------------------------------------------------------
0x0      0x1     status register     Used to communicate the current
                                     status of migration: not started,
                                     incoming, running, completed.
0x1      0x1     data register       Used to communicate data
                                     availability: data ready, data
                                     read.
0x2      0x7FD   reserved
0x800    0x800   data buffer         Used for data transfer between QEMU
                                     and SVSM.
--------------------------------------------------------------------------

The hypervisor is deemed untrusted in a confidential computing scenario.
Therefore, the only thing we want from the hypervisor is to provide a
communication channel over which the SVSM instances can communicate
without implementing the network stack. This patch should accomplish
just that. The rest of the work should be done in the SVSM.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants