From nobody Tue Apr 7 01:05:08 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1773752126; cv=none; d=zohomail.com; s=zohoarc; b=bebQlQDW1UPYDQOsnMes8QjD8jDHk8mvIIQWlAdEh7M0DVM91tUiAHKZ9OzVRlNhM7RKpu0S6LCcnemUZ+I/z2mv09ObI/4JJ1g4AAulHZxRIT2mjPGAPcGnlM7oGmL+pLBm1r6XqsVO5YvBmpMaat4pUbFSTf2qzlnB9wqlohE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1773752126; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=C4OeY00TqioDsqTaCkdbJqegZ4L5ieZAJ4YmiLwi1M0=; b=RgJnOW8cy56O8K4mdH3Ist682Ph3AZm2YZg9jwHCpmTIN9bn7XHIPgnwCdGBOEFIUOxMGUv/hy8/KruQiZUZ0oUd7u7rMtiGGSWtpoBF0zDcyha7CBGS5C5XZHSurX4gyej8Dsv72agzYBwTWR2IIQ6NIq/Rd/59nAOpccazvCk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1773752126185737.8099907604231; Tue, 17 Mar 2026 05:55:26 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w2TwU-0008V0-72; Tue, 17 Mar 2026 08:54:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1w2Sl2-0003Ss-6U for qemu-devel@nongnu.org; Tue, 17 Mar 2026 07:38:44 -0400 Received: from mail-wm1-x329.google.com ([2a00:1450:4864:20::329]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1w2Skx-0007sD-IM for qemu-devel@nongnu.org; Tue, 17 Mar 2026 07:38:41 -0400 Received: by mail-wm1-x329.google.com with SMTP id 5b1f17b1804b1-4856cd3f1ffso15050215e9.3 for ; Tue, 17 Mar 2026 04:38:38 -0700 (PDT) Received: from DesktopTC.localdomain (host-87-27-45-215.business.telecomitalia.it. [87.27.45.215]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4856eaee04fsm62721365e9.13.2026.03.17.04.38.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Mar 2026 04:38:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773747516; x=1774352316; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=C4OeY00TqioDsqTaCkdbJqegZ4L5ieZAJ4YmiLwi1M0=; b=cQKgiCYTYNqoGYiL/FdDj9mXpDUUt31ZMyseFUHKk3pbeKbMHTJn2s26HlWpImL+bp vFWpjHIBUuj/Y8dkyoPDlhiUN4uDr9StVySVdL3XcOpQkI5XRh03+RZw5N3uYuRp+KY4 gHTKTk5ALbfjm9lxXu58rWfk8G87zE75v6GAq4aap0XuHYf44x4noGU3HTOOvagpz0Vt ovB5u+jx9AuOM1PwQZONIX6wuLESllzPLd0+VVBM2M7K8jbhCPFKt0fHOcJdaoWCx6J7 GJ8ck9u6LhoSUl0ZCQEpvuGH20jf/D4ginjgQWfp2vTSpCskpMioRHfQ2BNQm6Mc3nDd XPHw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773747516; x=1774352316; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=C4OeY00TqioDsqTaCkdbJqegZ4L5ieZAJ4YmiLwi1M0=; b=FCb9VjKitQKxc0K7AZ7lAui5b7AeGqQLBTzRiJr7Ffz8oUoS+VwbN/UAca4G3RWttz zYgEVUpue1v2yndRns07ywtUg2/wfUao2izyXI/iQCiwhKXHyuTg12PpE68o0SyI9szK ikswqDgGzGAm20QiT6LdQ2uI186IbT2FRMpPouZMHOCAqN+H/z+LWSbcDR/8SKFNufiu YLZL5ErGKJPaL1A0rMwj8xRAeSc7BFKXXUFBdSjxxmN9Y5tf9Mw+lsNW1VZ7ZAGV4z0T vxlQLkgmw+j8+6KONl7+X7Ohs5bIgrZjR3AuyZraD8LIfU31N30+mnryWDT7fCyOWXGs wOLw== X-Gm-Message-State: AOJu0Yyb2f8ZuXAGH5BLsqaokxLTnG7x8uZUai3QbEb0iS3cRomqqD4K 65gOp0V0m3oWeNsZ9MRoVlM9RqmdQmQCn3AiqKuWm4tugwJJ2TSCyhgQeQKYLOW3 X-Gm-Gg: ATEYQzznjPkzVCIMPgyuNHG0H4Ip1egTlZDWelGxY6QdEwLXc8XyTgeOOyXs+XyWRwq Dp+nc1FBVhfG9to0jly7FSnfswj8k5xZxwAXkUQUc/l9rhGZl9RM9OqxExUfSAqVaoSkJYbt8b8 9Ia1uT6as37lJ3DJvU2tWxAC73gt8MRZRxsVQr4QeTiZxEnVDEdEHyLs13ubnzEBZqPIizQ+blE jyX6nGdVot7/9/I+JF95IMEwolA0WDTCG8m0fUrInhAqzrlft5wumtL3pyZMFqi4l/mF3iOIIdv pXuYjzB4ESNxtNuC+5urxZSIbcsEdlaI4pAJcqpeof4ZyCgJSPDmh/jNMqCUJTNC224aZaxdX6K gYzgQefZL8AiL1qgBqye4x/ixFLf8pEuoEP8QvwLIA3L9IjD8sl7fYKwcn0rkl/OHu1vDJ6oBEz ZV2RDJVWBst9cYjofHxfdgUwVyq5lNnKHqEgjm+/m7eULVk3TRX77xO9doYMoplyxCgKCFEaFYN Gmhc4Hd/UHN799yw+h6 X-Received: by 2002:a05:600c:8519:b0:485:5812:bb9e with SMTP id 5b1f17b1804b1-4855812bbddmr316994945e9.0.1773747515544; Tue, 17 Mar 2026 04:38:35 -0700 (PDT) From: Tommaso Califano To: qemu-devel@nongnu.org Cc: kvm@vger.kernel.org, Eduardo Habkost , Markus Armbruster , Zhao Liu , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , Marcelo Tosatti , Eric Blake , Oliver Steffen , Stefano Garzarella , Giuseppe Lettieri , Paolo Bonzini , Luigi Leonardi , Richard Henderson , Tommaso Califano Subject: [PATCH 1/5] i386/sev: Add sev-emulated QOM object with TCG support Date: Tue, 17 Mar 2026 12:38:36 +0100 Message-ID: <20260317113840.33017-2-califano.tommaso@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260317113840.33017-1-califano.tommaso@gmail.com> References: <20260317113840.33017-1-califano.tommaso@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::329; envelope-from=califano.tommaso@gmail.com; helo=mail-wm1-x329.google.com X-Spam_score_int: -3 X-Spam_score: -0.4 X-Spam_bar: / X-Spam_report: (-0.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, MIME_BASE64_TEXT=1.741, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Tue, 17 Mar 2026 08:54:34 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1773752128777154100 Content-Type: text/plain; charset="utf-8" QEMU's AMD SEV support requires KVM on costly AMD EPYC processors, limiting development and testing to users with specialized server hardware. This makes it hard to validate SEV guest behavior, like OVMF boots or SEV-aware software, on common dev machines. A solution to this is the emulation of SEV from the guest's perspective using TCG. This change begins this process with the exposure of the SEV CPUID leaf. In target/i386/cpu.c:cpu_x86_cpuid() case 0x8000001F: case 0x8000001F: *eax =3D *ebx =3D *ecx =3D *edx =3D 0; if (sev_enabled()) { *eax =3D 0x2; *eax |=3D sev_es_enabled() ? 0x8 : 0; *eax |=3D sev_snp_enabled() ? 0x10 : 0; *ebx =3D sev_get_cbit_position() & 0x3f; /* EBX[5:0] */ *ebx |=3D (sev_get_reduced_phys_bits() & 0x3f) << 6; /* EBX[11:6] */ } break; sev_enabled() verifies if the QOM object is TYPE_SEV_GUEST; TYPE_SEV_EMULATED is derived from TYPE_SEV_GUEST with SevEmulatedState to satisfy this check with minimal changes. In particular this allows to bypass all the sev_enabled() checks for future features. Since KVM hardware isn't available, override the QOM's kvm_init() and add a conditional confidential_guest_kvm_init() call during machine_init() to set up emulated confidential support using the ConfidentialGuestSupport structure. With this change it is possible to run a VM with the SEV CPUID active adding: -accel tcg \ -object sev-emulated,id=3Dsev0,cbitpos=3D47,reduced-phys-bits=3D1 \ -machine memory-encryption=3Dsev0 To the QEMU start arguments. Signed-off-by: Tommaso Califano --- accel/tcg/tcg-all.c | 18 ++++++++++++- qapi/qom.json | 15 +++++++++++ target/i386/sev.c | 65 +++++++++++++++++++++++++++++++++++++++++++++ target/i386/sev.h | 1 + 4 files changed, 98 insertions(+), 1 deletion(-) diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c index 8eb4a6b89e..d55827e214 100644 --- a/accel/tcg/tcg-all.c +++ b/accel/tcg/tcg-all.c @@ -45,7 +45,7 @@ #include "accel/accel-cpu-ops.h" #include "accel/tcg/cpu-ops.h" #include "internal-common.h" - +#include "system/confidential-guest-support.h" =20 struct TCGState { AccelState parent_obj; @@ -107,6 +107,9 @@ static int tcg_init_machine(AccelState *as, MachineStat= e *ms) unsigned max_threads =3D 1; =20 #ifndef CONFIG_USER_ONLY + int ret; + Error *local_err =3D NULL; + const char *cgs_type =3D NULL; CPUClass *cc =3D CPU_CLASS(object_class_by_name(target_cpu_type())); bool mttcg_supported =3D cc->tcg_ops->mttcg_supported; =20 @@ -163,6 +166,19 @@ static int tcg_init_machine(AccelState *as, MachineSta= te *ms) =20 #ifdef CONFIG_USER_ONLY qdev_create_fake_machine(); +#else + /* TCG SEV/Confidential Guest Support init */ + if (ms->cgs) { + cgs_type =3D object_get_typename(OBJECT(ms->cgs)); + + if (g_str_has_prefix(cgs_type, "sev-emulated")) { + ret =3D confidential_guest_kvm_init(ms->cgs, &local_err); + if (ret < 0) { + error_report_err(local_err); + return ret; + } + } + } #endif =20 return 0; diff --git a/qapi/qom.json b/qapi/qom.json index c653248f85..35cda819ec 100644 --- a/qapi/qom.json +++ b/qapi/qom.json @@ -1057,6 +1057,19 @@ '*handle': 'uint32', '*legacy-vm-type': 'OnOffAuto' } } =20 +## +# @SevEmulatedProperties: +# +# Properties for sev-emulated objects. +# This object functionally emulates AMD SEV hardware via TCG, so +# it does not require real hardware to run. +# +# Since: 10.1.0 +## +{ 'struct': 'SevEmulatedProperties', + 'base': 'SevGuestProperties', + 'data': {}} + ## # @SevSnpGuestProperties: # @@ -1241,6 +1254,7 @@ { 'name': 'secret_keyring', 'if': 'CONFIG_SECRET_KEYRING' }, 'sev-guest', + 'sev-emulated', 'sev-snp-guest', 'thread-context', 's390-pv-guest', @@ -1318,6 +1332,7 @@ 'secret_keyring': { 'type': 'SecretKeyringProperties', 'if': 'CONFIG_SECRET_KEYRING' }, 'sev-guest': 'SevGuestProperties', + 'sev-emulated': 'SevEmulatedProperties', 'sev-snp-guest': 'SevSnpGuestProperties', 'tdx-guest': 'TdxGuestProperties', 'thread-context': 'ThreadContextProperties', diff --git a/target/i386/sev.c b/target/i386/sev.c index 9dde972c11..2502e860e2 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -51,6 +51,7 @@ =20 OBJECT_DECLARE_TYPE(SevCommonState, SevCommonStateClass, SEV_COMMON) OBJECT_DECLARE_TYPE(SevGuestState, SevCommonStateClass, SEV_GUEST) +OBJECT_DECLARE_TYPE(SevEmulatedState, SevCommonStateClass, SEV_EMULATED) OBJECT_DECLARE_TYPE(SevSnpGuestState, SevCommonStateClass, SEV_SNP_GUEST) =20 /* hard code sha256 digest size */ @@ -177,6 +178,21 @@ struct SevGuestState { OnOffAuto legacy_vm_type; }; =20 +/** + * SevEmulatedState: + * + * The SevEmulatedState object is used for creating and managing a SEV emu= lated + * guest. + * + * # $QEMU \ + * -object sev-emulated,id=3Dsev0 \ + * -machine ...,memory-encryption=3Dsev0 + */ + +typedef struct SevEmulatedState { + SevGuestState parent_obj; +} SevEmulatedState; + struct SevSnpGuestState { SevCommonState parent_obj; =20 @@ -2936,6 +2952,46 @@ sev_guest_instance_init(Object *obj) sev_guest->legacy_vm_type =3D ON_OFF_AUTO_AUTO; } =20 +static int sev_emulated_init(ConfidentialGuestSupport *cgs, Error **errp) +{ + SevCommonState *sev_common =3D SEV_COMMON(cgs); + + /* + * The cbitpos value will be placed in bit positions 5:0 of the EBX + * register of CPUID 0x8000001F. We need to verify the range as the + * comparison with the host cbitpos is missing. + */ + if (sev_common->cbitpos < 32 || + sev_common->cbitpos > 63) { + error_setg(errp, "%s: cbitpos check failed, requested '%d'," + "the firmware requires >=3D32", + __func__, sev_common->cbitpos); + return -1; + } + + /* + * The reduced-phys-bits value will be placed in bit positions 11:6 of + * the EBX register of CPUID 0x8000001F, so verify the supplied value + * is in the range of 1 to 63. + */ + if (sev_common->reduced_phys_bits < 1 || + sev_common->reduced_phys_bits > 63) { + error_setg(errp, "%s: reduced_phys_bits check failed," + " it should be in the range of 1 to 63, requested '%d'", + __func__, sev_common->reduced_phys_bits); + return -1; + } + cgs->ready =3D true; + return 0; +} + +static void sev_emulated_class_init(ObjectClass *oc, const void *data) +{ + ConfidentialGuestSupportClass *klass =3D CONFIDENTIAL_GUEST_SUPPORT_CL= ASS(oc); + /* Override the sev-common method that uses kvm */ + klass->kvm_init =3D sev_emulated_init; +} + /* guest info specific sev/sev-es */ static const TypeInfo sev_guest_info =3D { .parent =3D TYPE_SEV_COMMON, @@ -2945,6 +3001,14 @@ static const TypeInfo sev_guest_info =3D { .class_init =3D sev_guest_class_init, }; =20 +/* emulated sev */ +static const TypeInfo sev_emulated_info =3D { + .parent =3D TYPE_SEV_GUEST, + .name =3D TYPE_SEV_EMULATED, + .instance_size =3D sizeof(SevEmulatedState), + .class_init =3D sev_emulated_class_init +}; + static void sev_snp_guest_get_policy(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) @@ -3207,6 +3271,7 @@ static void sev_register_types(void) { type_register_static(&sev_common_info); + type_register_static(&sev_emulated_info); type_register_static(&sev_guest_info); type_register_static(&sev_snp_guest_info); } diff --git a/target/i386/sev.h b/target/i386/sev.h index 4358df40e4..839656e2be 100644 --- a/target/i386/sev.h +++ b/target/i386/sev.h @@ -33,6 +33,7 @@ bool sev_snp_enabled(void); #if !defined(CONFIG_USER_ONLY) =20 #define TYPE_SEV_COMMON "sev-common" +#define TYPE_SEV_EMULATED "sev-emulated" #define TYPE_SEV_GUEST "sev-guest" #define TYPE_SEV_SNP_GUEST "sev-snp-guest" =20 --=20 2.53.0