Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging

* rust: miscellaneous fixes
* rust: qemu-api-macros: cleanup and add unit tests for TryInto
* rust: log: implement io::Write, avoid memory allocations
  when logging constant strings
* target/i386: fix usage of properties whenever accelerators
  change the default (e.g. vendor)
* target/i386: add support for TDVMCALL_SETUP_EVENT_NOTIFY_INTERRUPT
* target/i386: add support for booting an SEV VM from an IGVM file
* target/i386: unify cache model descriptions between CPUID 2,
  CPUID 4 and AMD specific CPUID 0x80000006
* target/i386: introduce cache models for recent Intel CPU models
* target/i386: mark some 0x80000000-0x80000008 bits as reserved on Intel
* target/i386: cleanups

# -----BEGIN PGP SIGNATURE-----
#
# iQFIBAABCgAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmh0v+sUHHBib256aW5p
# QHJlZGhhdC5jb20ACgkQv/vSX3jHroOQUQf8CTsCnl2xYrnrkVfSVj6kuAE+JYD6
# oLSXsOEG4yrVknuhwIfVsqNScmleJCdz85ej7CZxy3vzzgjLfmy7nwifKEIKku7E
# XO/Q3HbB898MnzqceQRmwe1AzELoj1Lave215CPhUBo60LCRPwaIZsiHprnNZgXi
# TyHlmywDVRjyFLtKkx3El0dnLAhFqPWeGh81CD5lPLZZJ+Wt2FuAw2zqSOGB2ztM
# FkJmunFJiaTItjyCN/uNvBSbDKecAHgCXvSCVNG3+I4U2R0gK1lcwm3TRo7yKia+
# HUHGa3UEXoIqlRfXdX6zuc8tW1/u6SPv+8WX53t204PAeSWDUrtIe9jZ4A==
# =y4/a
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 14 Jul 2025 04:29:31 EDT
# gpg:                using RSA key F13338574B662389866C7682BFFBD25F78C7AE83
# gpg:                issuer "pbonzini@redhat.com"
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full]
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>" [full]
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4  E2F7 7E15 100C CD36 69B1
#      Subkey fingerprint: F133 3857 4B66 2389 866C  7682 BFFB D25F 78C7 AE83

* tag 'for-upstream' of https://gitlab.com/bonzini/qemu: (77 commits)
  i386/cpu: Honor maximum value for CPUID.8000001DH.EAX[25:14]
  i386/cpu: Fix overflow of cache topology fields in CPUID.04H
  i386/cpu: Fix cpu number overflow in CPUID.01H.EBX[23:16]
  i386/cpu: Fix number of addressable IDs field for CPUID.01H.EBX[23:16]
  i386/cpu: Reorder CPUID leaves in cpu_x86_cpuid()
  tests/vm: bump FreeBSD image to 14.3
  tests/functional: test_x86_cpu_model_versions: remove dead tests
  i386/cpu: Mark CPUID 0x80000008 ECX bits[0:7] & [12:15] as reserved for Intel/Zhaoxin
  i386/cpu: Mark CPUID 0x80000007[EBX] as reserved for Intel
  i386/cpu: Mark EBX/ECX/EDX in CPUID 0x80000000 leaf as reserved for Intel
  i386/cpu: Enable 0x1f leaf for YongFeng by default
  i386/cpu: Enable 0x1f leaf for SapphireRapids by default
  i386/cpu: Enable 0x1f leaf for GraniteRapids by default
  i386/cpu: Enable 0x1f leaf for SierraForest by default
  i386/cpu: Enable 0x1f leaf for SierraForest by default
  i386/cpu: Add a "x-force-cpuid-0x1f" property
  i386/cpu: Introduce cache model for YongFeng
  i386/cpu: Introduce cache model for SapphireRapids
  i386/cpu: Introduce cache model for GraniteRapids
  i386/cpu: Introduce cache model for SierraForest
  ...

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi
2025-07-14 09:36:57 -04:00
55 changed files with 3927 additions and 633 deletions
+43
View File
@@ -14,15 +14,58 @@
#include "qemu/osdep.h"
#include "system/confidential-guest-support.h"
#include "qapi/error.h"
OBJECT_DEFINE_ABSTRACT_TYPE(ConfidentialGuestSupport,
confidential_guest_support,
CONFIDENTIAL_GUEST_SUPPORT,
OBJECT)
static bool check_support(ConfidentialGuestPlatformType platform,
uint16_t platform_version, uint8_t highest_vtl,
uint64_t shared_gpa_boundary)
{
/* Default: no support. */
return false;
}
static int set_guest_state(hwaddr gpa, uint8_t *ptr, uint64_t len,
ConfidentialGuestPageType memory_type,
uint16_t cpu_index, Error **errp)
{
error_setg(errp,
"Setting confidential guest state is not supported for this platform");
return -1;
}
static int set_guest_policy(ConfidentialGuestPolicyType policy_type,
uint64_t policy,
void *policy_data1, uint32_t policy_data1_size,
void *policy_data2, uint32_t policy_data2_size,
Error **errp)
{
error_setg(errp,
"Setting confidential guest policy is not supported for this platform");
return -1;
}
static int get_mem_map_entry(int index, ConfidentialGuestMemoryMapEntry *entry,
Error **errp)
{
error_setg(
errp,
"Obtaining the confidential guest memory map is not supported for this platform");
return -1;
}
static void confidential_guest_support_class_init(ObjectClass *oc,
const void *data)
{
ConfidentialGuestSupportClass *cgsc = CONFIDENTIAL_GUEST_SUPPORT_CLASS(oc);
cgsc->check_support = check_support;
cgsc->set_guest_state = set_guest_state;
cgsc->set_guest_policy = set_guest_policy;
cgsc->get_mem_map_entry = get_mem_map_entry;
}
static void confidential_guest_support_init(Object *obj)
+51
View File
@@ -0,0 +1,51 @@
/*
* QEMU IGVM interface
*
* Copyright (C) 2023-2024 SUSE
*
* Authors:
* Roy Hopkins <roy.hopkins@randomman.co.uk>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include "system/igvm-cfg.h"
#include "igvm.h"
#include "qom/object_interfaces.h"
static char *get_igvm(Object *obj, Error **errp)
{
IgvmCfg *igvm = IGVM_CFG(obj);
return g_strdup(igvm->filename);
}
static void set_igvm(Object *obj, const char *value, Error **errp)
{
IgvmCfg *igvm = IGVM_CFG(obj);
g_free(igvm->filename);
igvm->filename = g_strdup(value);
}
OBJECT_DEFINE_TYPE_WITH_INTERFACES(IgvmCfg, igvm_cfg, IGVM_CFG, OBJECT,
{ TYPE_USER_CREATABLE }, { NULL })
static void igvm_cfg_class_init(ObjectClass *oc, const void *data)
{
IgvmCfgClass *igvmc = IGVM_CFG_CLASS(oc);
object_class_property_add_str(oc, "file", get_igvm, set_igvm);
object_class_property_set_description(oc, "file",
"Set the IGVM filename to use");
igvmc->process = qigvm_process_file;
}
static void igvm_cfg_init(Object *obj)
{
}
static void igvm_cfg_finalize(Object *obj)
{
}
+988
View File
File diff suppressed because it is too large Load Diff
+22
View File
@@ -0,0 +1,22 @@
/*
* QEMU IGVM configuration backend for Confidential Guests
*
* Copyright (C) 2023-2024 SUSE
*
* Authors:
* Roy Hopkins <roy.hopkins@randomman.co.uk>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef BACKENDS_IGVM_H
#define BACKENDS_IGVM_H
#include "system/confidential-guest-support.h"
#include "system/igvm-cfg.h"
#include "qapi/error.h"
int qigvm_process_file(IgvmCfg *igvm, ConfidentialGuestSupport *cgs,
bool onlyVpContext, Error **errp);
#endif
+5
View File
@@ -34,6 +34,11 @@ if have_vhost_user_crypto
endif
system_ss.add(when: gio, if_true: files('dbus-vmstate.c'))
system_ss.add(when: 'CONFIG_SGX', if_true: files('hostmem-epc.c'))
if igvm.found()
system_ss.add(igvm)
system_ss.add(files('igvm-cfg.c'), igvm)
system_ss.add(files('igvm.c'), igvm)
endif
system_ss.add(when: 'CONFIG_SPDM_SOCKET', if_true: files('spdm-socket.c'))
+6 -5
View File
@@ -351,7 +351,7 @@ Writing procedural macros
'''''''''''''''''''''''''
By conventions, procedural macros are split in two functions, one
returning ``Result<proc_macro2::TokenStream, MacroError>`` with the body of
returning ``Result<proc_macro2::TokenStream, syn::Error>`` with the body of
the procedural macro, and the second returning ``proc_macro::TokenStream``
which is the actual procedural macro. The former's name is the same as
the latter with the ``_or_error`` suffix. The code for the latter is more
@@ -361,18 +361,19 @@ from the type after ``as`` in the invocation of ``parse_macro_input!``::
#[proc_macro_derive(Object)]
pub fn derive_object(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let expanded = derive_object_or_error(input).unwrap_or_else(Into::into);
TokenStream::from(expanded)
derive_object_or_error(input)
.unwrap_or_else(syn::Error::into_compile_error)
.into()
}
The ``qemu_api_macros`` crate has utility functions to examine a
``DeriveInput`` and perform common checks (e.g. looking for a struct
with named fields). These functions return ``Result<..., MacroError>``
with named fields). These functions return ``Result<..., syn::Error>``
and can be used easily in the procedural macro function::
fn derive_object_or_error(input: DeriveInput) ->
Result<proc_macro2::TokenStream, MacroError>
Result<proc_macro2::TokenStream, Error>
{
is_c_repr(&input, "#[derive(Object)]")?;
+28 -2
View File
@@ -57,10 +57,17 @@
#
# @memory: The firmware is to be mapped into memory.
#
# @igvm: The firmware is defined by a file conforming to the IGVM
# specification and mapped into memory according to directives
# defined in the file. This is similar to @memory but may
# include additional processing defined by the IGVM file
# including initial CPU state or population of metadata into
# the guest address space. Since: 10.1
#
# Since: 3.0
##
{ 'enum' : 'FirmwareDevice',
'data' : [ 'flash', 'kernel', 'memory' ] }
'data' : [ 'flash', 'kernel', 'memory', 'igvm' ] }
##
# @FirmwareArchitecture:
@@ -377,6 +384,24 @@
{ 'struct' : 'FirmwareMappingMemory',
'data' : { 'filename' : 'str' } }
##
# @FirmwareMappingIgvm:
#
# Describes loading and mapping properties for the firmware executable,
# when @FirmwareDevice is @igvm.
#
# @filename: Identifies the IGVM file containing the firmware executable
# along with other information used to configure the initial
# state of the guest. The IGVM file may be shared by multiple
# virtual machine definitions. This corresponds to creating
# an object on the command line with "-object igvm-cfg,
# file=@filename".
#
# Since: 10.1
##
{ 'struct' : 'FirmwareMappingIgvm',
'data' : { 'filename' : 'str' } }
##
# @FirmwareMapping:
#
@@ -393,7 +418,8 @@
'discriminator' : 'device',
'data' : { 'flash' : 'FirmwareMappingFlash',
'kernel' : 'FirmwareMappingKernel',
'memory' : 'FirmwareMappingMemory' } }
'memory' : 'FirmwareMappingMemory',
'igvm' : 'FirmwareMappingIgvm' } }
##
# @Firmware:
@@ -1,3 +1,5 @@
.. _amd-sev:
AMD Secure Encrypted Virtualization (SEV)
=========================================
+173
View File
@@ -0,0 +1,173 @@
Independent Guest Virtual Machine (IGVM) support
================================================
IGVM files are designed to encapsulate all the information required to launch a
virtual machine on any given virtualization stack in a deterministic way. This
allows the cryptographic measurement of initial guest state for Confidential
Guests to be calculated when the IGVM file is built, allowing a relying party to
verify the initial state of a guest via a remote attestation.
Although IGVM files are designed with Confidential Computing in mind, they can
also be used to configure non-confidential guests. Multiple platforms can be
defined by a single IGVM file, allowing a single IGVM file to configure a
virtual machine that can run on, for example, TDX, SEV and non-confidential
hosts.
QEMU supports IGVM files through the user-creatable ``igvm-cfg`` object. This
object is used to define the filename of the IGVM file to process. A reference
to the object is added to the ``-machine`` to configure the virtual machine
to use the IGVM file for configuration.
Confidential platform support is provided through the use of
the ``ConfidentialGuestSupport`` object. If the virtual machine provides an
instance of this object then this is used by the IGVM loader to configure the
isolation properties of the directives within the file.
Further Information on IGVM
---------------------------
Information about the IGVM format, including links to the format specification
and documentation for the Rust and C libraries can be found at the project
repository:
https://github.com/microsoft/igvm
Supported Platforms
-------------------
Currently, IGVM files can be provided for Confidential Guests on host systems
that support AMD SEV, SEV-ES and SEV-SNP with KVM. IGVM files can also be
provided for non-confidential guests.
Limitations when using IGVM with AMD SEV, SEV-ES and SEV-SNP
------------------------------------------------------------
IGVM files configure the initial state of the guest using a set of directives.
Not every directive is supported by every Confidential Guest type. For example,
AMD SEV does not support encrypted save state regions, therefore setting the
initial CPU state using IGVM for SEV is not possible. When an IGVM file contains
directives that are not supported for the active platform, an error is generated
and the guest launch is aborted.
The table below describes the list of directives that are supported for SEV,
SEV-ES, SEV-SNP and non-confidential platforms.
.. list-table:: SEV, SEV-ES, SEV-SNP & non-confidential Supported Directives
:widths: 35 65
:header-rows: 1
* - IGVM directive
- Notes
* - IGVM_VHT_PAGE_DATA
- ``NORMAL`` zero, measured and unmeasured page types are supported. Other
page types result in an error.
* - IGVM_VHT_PARAMETER_AREA
-
* - IGVM_VHT_PARAMETER_INSERT
-
* - IGVM_VHT_VP_COUNT_PARAMETER
- The guest parameter page is populated with the CPU count.
* - IGVM_VHT_ENVIRONMENT_INFO_PARAMETER
- The ``memory_is_shared`` parameter is set to 1 in the guest parameter
page.
.. list-table:: Additional SEV, SEV-ES & SEV_SNP Supported Directives
:widths: 25 75
:header-rows: 1
* - IGVM directive
- Notes
* - IGVM_VHT_MEMORY_MAP
- The memory map page is populated using entries from the E820 table.
* - IGVM_VHT_REQUIRED_MEMORY
- Ensures memory is available in the guest at the specified range.
.. list-table:: Additional SEV-ES & SEV-SNP Supported Directives
:widths: 25 75
:header-rows: 1
* - IGVM directive
- Notes
* - IGVM_VHT_VP_CONTEXT
- Setting of the initial CPU state for the boot CPU and additional CPUs is
supported with limitations on the fields that can be provided in the
VMSA. See below for details on which fields are supported.
Initial CPU state with VMSA
---------------------------
The initial state of guest CPUs can be defined in the IGVM file for AMD SEV-ES
and SEV-SNP. The state data is provided as a VMSA structure as defined in Table
B-4 in the AMD64 Architecture Programmer's Manual, Volume 2 [1].
The IGVM VMSA is translated to CPU state in QEMU which is then synchronized
by KVM to the guest VMSA during the launch process where it contributes to the
launch measurement. See :ref:`amd-sev` for details on the launch process and
guest launch measurement.
It is important that no information is lost or changed when translating the
VMSA provided by the IGVM file into the VSMA that is used to launch the guest.
Therefore, QEMU restricts the VMSA fields that can be provided in the IGVM
VMSA structure to the following registers:
RAX, RCX, RDX, RBX, RBP, RSI, RDI, R8-R15, RSP, RIP, CS, DS, ES, FS, GS, SS,
CR0, CR3, CR4, XCR0, EFER, PAT, GDT, IDT, LDTR, TR, DR6, DR7, RFLAGS, X87_FCW,
MXCSR.
When processing the IGVM file, QEMU will check if any fields other than the
above are non-zero and generate an error if this is the case.
KVM uses a hardcoded GPA of 0xFFFFFFFFF000 for the VMSA. When an IGVM file
defines initial CPU state, the GPA for each VMSA must match this hardcoded
value.
Firmware Images with IGVM
-------------------------
When an IGVM filename is specified for a Confidential Guest Support object it
overrides the default handling of system firmware: the firmware image, such as
an OVMF binary should be contained as a payload of the IGVM file and not
provided as a flash drive or via the ``-bios`` parameter. The default QEMU
firmware is not automatically populated into the guest memory space.
If an IGVM file is provided along with either the ``-bios`` parameter or pflash
devices then an error is displayed and the guest startup is aborted.
Running a guest configured using IGVM
-------------------------------------
To run a guest configured with IGVM you firstly need to generate an IGVM file
that contains a guest configuration compatible with the platform you are
targeting.
The ``buildigvm`` tool [2] is an example of a tool that can be used to generate
IGVM files for non-confidential X86 platforms as well as for SEV, SEV-ES and
SEV-SNP confidential platforms.
Example using this tool to generate an IGVM file for AMD SEV-SNP::
buildigvm --firmware /path/to/OVMF.fd --output sev-snp.igvm \
--cpucount 4 sev-snp
To run a guest configured with the generated IGVM you need to add an
``igvm-cfg`` object and refer to it from the ``-machine`` parameter:
Example (for AMD SEV)::
qemu-system-x86_64 \
<other parameters> \
-machine ...,confidential-guest-support=sev0,igvm-cfg=igvm0 \
-object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1 \
-object igvm-cfg,id=igvm0,file=/path/to/sev-snp.igvm
References
----------
[1] AMD64 Architecture Programmer's Manual, Volume 2: System Programming
Rev 3.41
https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/programmer-references/24593.pdf
[2] ``buildigvm`` - A tool to build example IGVM files containing OVMF firmware
https://github.com/roy-hopkins/buildigvm
+1
View File
@@ -38,5 +38,6 @@ or Hypervisor.Framework.
security
multi-process
confidential-guest-support
igvm
vm-templating
sriov
+16 -1
View File
@@ -81,7 +81,10 @@
{ "qemu64-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },\
{ "athlon-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },
GlobalProperty pc_compat_10_0[] = {};
GlobalProperty pc_compat_10_0[] = {
{ TYPE_X86_CPU, "x-consistent-cache", "false" },
{ TYPE_X86_CPU, "x-vendor-cpuid-only-v2", "false" },
};
const size_t pc_compat_10_0_len = G_N_ELEMENTS(pc_compat_10_0);
GlobalProperty pc_compat_9_2[] = {};
@@ -1827,6 +1830,18 @@ static void pc_machine_class_init(ObjectClass *oc, const void *data)
object_class_property_add_bool(oc, "fd-bootchk",
pc_machine_get_fd_bootchk,
pc_machine_set_fd_bootchk);
#if defined(CONFIG_IGVM)
object_class_property_add_link(oc, "igvm-cfg",
TYPE_IGVM_CFG,
offsetof(X86MachineState, igvm),
object_property_allow_set_link,
OBJ_PROP_LINK_STRONG);
object_class_property_set_description(oc, "igvm-cfg",
"Set IGVM configuration");
#endif
}
static const TypeInfo pc_machine_info = {
+10
View File
@@ -366,6 +366,16 @@ static void pc_init1(MachineState *machine, const char *pci_type)
x86_nvdimm_acpi_dsmio,
x86ms->fw_cfg, OBJECT(pcms));
}
#if defined(CONFIG_IGVM)
/* Apply guest state from IGVM if supplied */
if (x86ms->igvm) {
if (IGVM_CFG_GET_CLASS(x86ms->igvm)
->process(x86ms->igvm, machine->cgs, false, &error_fatal) < 0) {
g_assert_not_reached();
}
}
#endif
}
typedef enum PCSouthBridgeOption {
+10
View File
@@ -325,6 +325,16 @@ static void pc_q35_init(MachineState *machine)
x86_nvdimm_acpi_dsmio,
x86ms->fw_cfg, OBJECT(pcms));
}
#if defined(CONFIG_IGVM)
/* Apply guest state from IGVM if supplied */
if (x86ms->igvm) {
if (IGVM_CFG_GET_CLASS(x86ms->igvm)
->process(x86ms->igvm, machine->cgs, false, &error_fatal) < 0) {
g_assert_not_reached();
}
}
#endif
}
#define DEFINE_Q35_MACHINE(major, minor) \
+28 -3
View File
@@ -220,7 +220,13 @@ void pc_system_firmware_init(PCMachineState *pcms,
BlockBackend *pflash_blk[ARRAY_SIZE(pcms->flash)];
if (!pcmc->pci_enabled) {
x86_bios_rom_init(X86_MACHINE(pcms), "bios.bin", rom_memory, true);
/*
* If an IGVM file is specified then the firmware must be provided
* in the IGVM file.
*/
if (!X86_MACHINE(pcms)->igvm) {
x86_bios_rom_init(X86_MACHINE(pcms), "bios.bin", rom_memory, true);
}
return;
}
@@ -240,8 +246,13 @@ void pc_system_firmware_init(PCMachineState *pcms,
}
if (!pflash_blk[0]) {
/* Machine property pflash0 not set, use ROM mode */
x86_bios_rom_init(X86_MACHINE(pcms), "bios.bin", rom_memory, false);
/*
* Machine property pflash0 not set, use ROM mode unless using IGVM,
* in which case the firmware must be provided by the IGVM file.
*/
if (!X86_MACHINE(pcms)->igvm) {
x86_bios_rom_init(X86_MACHINE(pcms), "bios.bin", rom_memory, false);
}
} else {
if (kvm_enabled() && !kvm_readonly_mem_enabled()) {
/*
@@ -257,6 +268,20 @@ void pc_system_firmware_init(PCMachineState *pcms,
}
pc_system_flash_cleanup_unused(pcms);
/*
* The user should not have specified any pflash devices when using IGVM
* to configure the guest.
*/
if (X86_MACHINE(pcms)->igvm) {
for (i = 0; i < ARRAY_SIZE(pcms->flash); i++) {
if (pcms->flash[i]) {
error_report("pflash devices cannot be configured when "
"using IGVM");
exit(1);
}
}
}
}
void x86_firmware_configure(hwaddr gpa, void *ptr, int size)
+3
View File
@@ -25,6 +25,7 @@
#include "hw/intc/ioapic.h"
#include "hw/isa/isa.h"
#include "qom/object.h"
#include "system/igvm-cfg.h"
struct X86MachineClass {
MachineClass parent;
@@ -92,6 +93,8 @@ struct X86MachineState {
* which means no limitation on the guest's bus locks.
*/
uint64_t bus_lock_ratelimit;
IgvmCfg *igvm;
};
#define X86_MACHINE_SMM "smm"
+2
View File
@@ -84,6 +84,8 @@ typedef struct QEMULogItem {
extern const QEMULogItem qemu_log_items[];
ssize_t rust_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
bool qemu_set_log(int log_flags, Error **errp);
bool qemu_set_log_filename(const char *filename, Error **errp);
bool qemu_set_log_filename_flags(const char *name, int flags, Error **errp);
@@ -19,6 +19,7 @@
#define QEMU_CONFIDENTIAL_GUEST_SUPPORT_H
#include "qom/object.h"
#include "exec/hwaddr.h"
#define TYPE_CONFIDENTIAL_GUEST_SUPPORT "confidential-guest-support"
OBJECT_DECLARE_TYPE(ConfidentialGuestSupport,
@@ -26,6 +27,40 @@ OBJECT_DECLARE_TYPE(ConfidentialGuestSupport,
CONFIDENTIAL_GUEST_SUPPORT)
typedef enum ConfidentialGuestPlatformType {
CGS_PLATFORM_SEV,
CGS_PLATFORM_SEV_ES,
CGS_PLATFORM_SEV_SNP,
} ConfidentialGuestPlatformType;
typedef enum ConfidentialGuestMemoryType {
CGS_MEM_RAM,
CGS_MEM_RESERVED,
CGS_MEM_ACPI,
CGS_MEM_NVS,
CGS_MEM_UNUSABLE,
} ConfidentialGuestMemoryType;
typedef struct ConfidentialGuestMemoryMapEntry {
uint64_t gpa;
uint64_t size;
ConfidentialGuestMemoryType type;
} ConfidentialGuestMemoryMapEntry;
typedef enum ConfidentialGuestPageType {
CGS_PAGE_TYPE_NORMAL,
CGS_PAGE_TYPE_VMSA,
CGS_PAGE_TYPE_ZERO,
CGS_PAGE_TYPE_UNMEASURED,
CGS_PAGE_TYPE_SECRETS,
CGS_PAGE_TYPE_CPUID,
CGS_PAGE_TYPE_REQUIRED_MEMORY,
} ConfidentialGuestPageType;
typedef enum ConfidentialGuestPolicyType {
GUEST_POLICY_SEV,
} ConfidentialGuestPolicyType;
struct ConfidentialGuestSupport {
Object parent;
@@ -64,6 +99,59 @@ typedef struct ConfidentialGuestSupportClass {
int (*kvm_init)(ConfidentialGuestSupport *cgs, Error **errp);
int (*kvm_reset)(ConfidentialGuestSupport *cgs, Error **errp);
/*
* Check to see if this confidential guest supports a particular
* platform or configuration.
*
* Return true if supported or false if not supported.
*/
bool (*check_support)(ConfidentialGuestPlatformType platform,
uint16_t platform_version, uint8_t highest_vtl,
uint64_t shared_gpa_boundary);
/*
* Configure part of the state of a guest for a particular set of data, page
* type and gpa. This can be used for example to pre-populate and measure
* guest memory contents, define private ranges or set the initial CPU state
* for one or more CPUs.
*
* If memory_type is CGS_PAGE_TYPE_VMSA then ptr points to the initial CPU
* context for a virtual CPU. The format of the data depends on the type of
* confidential virtual machine. For example, for SEV-ES ptr will point to a
* vmcb_save_area structure that should be copied into guest memory at the
* address specified in gpa. The cpu_index parameter contains the index of
* the CPU the VMSA applies to.
*/
int (*set_guest_state)(hwaddr gpa, uint8_t *ptr, uint64_t len,
ConfidentialGuestPageType memory_type,
uint16_t cpu_index, Error **errp);
/*
* Set the guest policy. The policy can be used to configure the
* confidential platform, such as if debug is enabled or not and can contain
* information about expected launch measurements, signed verification of
* guest configuration and other platform data.
*
* The format of the policy data is specific to each platform. For example,
* SEV-SNP uses a policy bitfield in the 'policy' argument and provides an
* ID block and ID authentication in the 'policy_data' parameters. The type
* of policy data is identified by the 'policy_type' argument.
*/
int (*set_guest_policy)(ConfidentialGuestPolicyType policy_type,
uint64_t policy,
void *policy_data1, uint32_t policy_data1_size,
void *policy_data2, uint32_t policy_data2_size,
Error **errp);
/*
* Iterate the system memory map, getting the entry with the given index
* that can be populated into guest memory.
*
* Returns 0 for ok, 1 if the index is out of range and -1 on error.
*/
int (*get_mem_map_entry)(int index, ConfidentialGuestMemoryMapEntry *entry,
Error **errp);
} ConfidentialGuestSupportClass;
static inline int confidential_guest_kvm_init(ConfidentialGuestSupport *cgs,
+49
View File
@@ -0,0 +1,49 @@
/*
* QEMU IGVM interface
*
* Copyright (C) 2024 SUSE
*
* Authors:
* Roy Hopkins <roy.hopkins@randomman.co.uk>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef QEMU_IGVM_CFG_H
#define QEMU_IGVM_CFG_H
#include "qom/object.h"
typedef struct IgvmCfg {
ObjectClass parent_class;
/*
* filename: Filename that specifies a file that contains the configuration
* of the guest in Independent Guest Virtual Machine (IGVM)
* format.
*/
char *filename;
} IgvmCfg;
typedef struct IgvmCfgClass {
ObjectClass parent_class;
/*
* If an IGVM filename has been specified then process the IGVM file.
* Performs a no-op if no filename has been specified.
* If onlyVpContext is true then only the IGVM_VHT_VP_CONTEXT entries
* in the IGVM file will be processed, allowing information about the
* CPU state to be determined before processing the entire file.
*
* Returns 0 for ok and -1 on error.
*/
int (*process)(IgvmCfg *cfg, ConfidentialGuestSupport *cgs,
bool onlyVpContext, Error **errp);
} IgvmCfgClass;
#define TYPE_IGVM_CFG "igvm-cfg"
OBJECT_DECLARE_TYPE(IgvmCfg, IgvmCfgClass, IGVM_CFG)
#endif
+7 -1
View File
@@ -963,7 +963,13 @@ struct kvm_tdx_cmd {
struct kvm_tdx_capabilities {
__u64 supported_attrs;
__u64 supported_xfam;
__u64 reserved[254];
__u64 kernel_tdvmcallinfo_1_r11;
__u64 user_tdvmcallinfo_1_r11;
__u64 kernel_tdvmcallinfo_1_r12;
__u64 user_tdvmcallinfo_1_r12;
__u64 reserved[250];
/* Configurable CPUID bits for userspace */
struct kvm_cpuid2 cpuid;
+4
View File
@@ -459,6 +459,10 @@ struct kvm_run {
__u64 leaf;
__u64 r11, r12, r13, r14;
} get_tdvmcall_info;
struct {
__u64 ret;
__u64 vector;
} setup_event_notify;
};
} tdx;
/* Fix the size of the union. */

Some files were not shown because too many files have changed in this diff Show More