From nobody Fri Aug 21 21:27:09 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1787328783; cv=none; d=zohomail.com; s=zohoarc; b=fRW+eEXDmndIt+OkH7cxk0QGBFvr6TgGk9EzwO6JE4ptCD2QwzrgkIUYvn8FjnfiDAz9P2zb+fEXs5ufeE2phskfCEM/jMfohQQwKRyl8iHDc8rFmwPNDkqpMzEag+b2S8frOKKPKOnZy+pvRETC2r1w/728ti2UM6cUq1Ir8bo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787328783; 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=G6F9RKoKFbGpAk50ubZ3jB4iYhTRkoZxZqSHzIMo3fs=; b=Civ7sdyay+2a7LEKEYmnrKOpMsY5na1bvqTeC5pinklKDyxXbdd8TQWhnHoyoExJm0T+plvIKydP6Qyc+NsmVOTjG8eeZS1XEV77UnVrLjygnnLz67Hh+eaA1QzOwMeZyR5p0V5aS+1AompJtX1zwOLKaFKvOsMPJpy+soitRI0= 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=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787328783090765.796774868713; Fri, 21 Aug 2026 09:13:03 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wxRpr-0006Sk-EQ; Fri, 21 Aug 2026 12:11:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRpp-0006SM-U2 for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:13 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRpo-0001XB-Dq for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:13 -0400 Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-643-muH3uyG3N7elDvkGIMs81Q-1; Fri, 21 Aug 2026 12:11:07 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C206D1953987; Fri, 21 Aug 2026 16:11:05 +0000 (UTC) Received: from sirius.home.kraxel.org (unknown [10.44.48.30]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 69AA31955F70; Fri, 21 Aug 2026 16:11:04 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 4C2971800604; Fri, 21 Aug 2026 18:11:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787328671; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=G6F9RKoKFbGpAk50ubZ3jB4iYhTRkoZxZqSHzIMo3fs=; b=BDBCDRSARfEPA86OdWhbuzbXkquPN/HjkTOGIYERgyyYMNQn2nZW0jA1istuWkhcflFVLu vps2AgqgEQ8a8CQFLsvAUdRnT0lvYghzrn/wxGqs7Ktkrms9n5F5/ndp2Z5uPLiRo+TwLl cjVJ9YtkgdIJPnlOd7v9BvnVd3FlDhY= X-MC-Unique: muH3uyG3N7elDvkGIMs81Q-1 X-Mimecast-MFC-AGG-ID: muH3uyG3N7elDvkGIMs81Q_1787328666 From: Gerd Hoffmann To: qemu-devel@nongnu.org Cc: Ani Sinha , Cornelia Huck , Peter Maydell , Zhao Liu , Peter Xu , qemu-arm@nongnu.org, Pierrick Bouvier , Gerd Hoffman , "Michael S. Tsirkin" , Stefano Garzarella , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Laurent Vivier , Fabiano Rosas , Paolo Bonzini Subject: [PULL 01/12] MAINTAINERS: elevating myself to be a maintainer for igvm Date: Fri, 21 Aug 2026 18:10:49 +0200 Message-ID: <20260821161103.3489298-2-kraxel@redhat.com> In-Reply-To: <20260821161103.3489298-1-kraxel@redhat.com> References: <20260821161103.3489298-1-kraxel@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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=lists1p.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 9 X-Spam_score: 0.9 X-Spam_bar: / X-Spam_report: (0.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.341, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=0.001, RCVD_IN_SBL_CSS=3.335, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action 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 @redhat.com) X-ZM-MESSAGEID: 1787328784212158500 Content-Type: text/plain; charset="utf-8" From: Ani Sinha I have worked enough on the igvm to be confident to elevate myself to a maintainer role. Signed-off-by: Ani Sinha Message-ID: <20260818090905.87090-1-anisinha@redhat.com> Signed-off-by: Gerd Hoffmann --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index b51f5c3e6022..9e0a2a656f4c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4118,7 +4118,7 @@ F: tests/uefi-test-tools/ IGVM Firmware M: Gerd Hoffmann M: Stefano Garzarella -R: Ani Sinha +M: Ani Sinha S: Maintained F: backends/igvm*.c F: docs/system/igvm.rst --=20 2.55.0 From nobody Fri Aug 21 21:27:09 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1787328795; cv=none; d=zohomail.com; s=zohoarc; b=fUGcTq5fT2eSBM1aRBViymg7vg8ojA2My6TYl9g6PoNMZ4Xe8bMtf/3HTmIhAMCux5ICWq54hCaN/z9STkk14V1g6DYXDI4rrPYu0VhoHp+LSRUx1eOfPoJX3XnytFvjgq45MFJvAzZXpd9BSbOAMDnrlXYkBZFqHkQ0S4VJTiI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787328795; 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=dGUzv5WHptor2idlHZr5nwRiEW5XDSx77shBFL6pTfI=; b=AfKBBx7WFbQAXRxNA7roBuuwvieXhOA4dEV291jmG8D8lRVpk4e18MzxAzE83aUxFIaIPcK8MzDso6OVRl/X74qwH4Q+KP5p3wtEAiHNtIZXIlWo7hNaQCMsHQlyiIP6/q/h9jff0IzowUfYBHRv74kSuO8uQ0UNwr0zY53/ce8= 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=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787328795787604.0241556485418; Fri, 21 Aug 2026 09:13:15 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wxRps-0006Ta-7S; Fri, 21 Aug 2026 12:11:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRpq-0006SU-CW for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:14 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRpo-0001XA-Dm for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:14 -0400 Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-637-pzBuqZobOeGjCKv6aKx5ow-1; Fri, 21 Aug 2026 12:11:09 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id F3E571954221; Fri, 21 Aug 2026 16:11:07 +0000 (UTC) Received: from sirius.home.kraxel.org (unknown [10.44.48.30]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id D08A81800346; Fri, 21 Aug 2026 16:11:06 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 632811800613; Fri, 21 Aug 2026 18:11:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787328671; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=dGUzv5WHptor2idlHZr5nwRiEW5XDSx77shBFL6pTfI=; b=H54z4KF8UARePuPljyAi4F3Dc/LBriR6GeZaHwVItuIGkBTpjzHWrsYMBSVsPvTymYNG0e zu4+5/CpcJa3KIa+FssKAYkNwPo7qBQ1GDRF5fSPojcwtuyxAVEwI7vGEVqMeJ26h2mgdW g1aUahAlB6dUytaEHmaPvpqffzag1/k= X-MC-Unique: pzBuqZobOeGjCKv6aKx5ow-1 X-Mimecast-MFC-AGG-ID: pzBuqZobOeGjCKv6aKx5ow_1787328668 From: Gerd Hoffmann To: qemu-devel@nongnu.org Cc: Ani Sinha , Cornelia Huck , Peter Maydell , Zhao Liu , Peter Xu , qemu-arm@nongnu.org, Pierrick Bouvier , Gerd Hoffman , "Michael S. Tsirkin" , Stefano Garzarella , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Laurent Vivier , Fabiano Rosas , Paolo Bonzini , Alexander Graf Subject: [PULL 02/12] igvm: store IgvmCfg pointer in QIgvm Date: Fri, 21 Aug 2026 18:10:50 +0200 Message-ID: <20260821161103.3489298-3-kraxel@redhat.com> In-Reply-To: <20260821161103.3489298-1-kraxel@redhat.com> References: <20260821161103.3489298-1-kraxel@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 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=lists1p.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 9 X-Spam_score: 0.9 X-Spam_bar: / X-Spam_report: (0.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.341, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=0.001, RCVD_IN_SBL_CSS=3.335, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action 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 @redhat.com) X-ZM-MESSAGEID: 1787328796471158500 Content-Type: text/plain; charset="utf-8" Store a pointer to IgvmCfg instead of only IgvmFile in QIgvm. Allows to store additional state in the (persistent) IgvmCfg struct. Reviewed-by: Ani Sinha Reviewed-by: Alexander Graf Signed-off-by: Gerd Hoffmann Message-ID: <20260817142010.80693-2-anisinha@redhat.com> Signed-off-by: Gerd Hoffmann --- include/system/igvm-internal.h | 2 +- backends/igvm.c | 57 ++++++++++++++++++++-------------- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/include/system/igvm-internal.h b/include/system/igvm-internal.h index 7eb3792ed8c5..b5720fae0c00 100644 --- a/include/system/igvm-internal.h +++ b/include/system/igvm-internal.h @@ -43,7 +43,7 @@ typedef struct QIgvmParameterData { * file. */ struct QIgvm { - IgvmHandle file; + IgvmCfg *cfg; MachineState *machine_state; ConfidentialGuestSupportClass *cgsc; uint32_t compatibility_mask; diff --git a/backends/igvm.c b/backends/igvm.c index 80e87fe6029a..534032fed812 100644 --- a/backends/igvm.c +++ b/backends/igvm.c @@ -178,7 +178,8 @@ static int qigvm_handler(QIgvm *ctx, IgvmVariableHeader= Type raw_type, if (handlers[handler].type !=3D type) { continue; } - header_handle =3D igvm_get_header(ctx->file, handlers[handler].sec= tion, + header_handle =3D igvm_get_header(ctx->cfg->file, + handlers[handler].section, ctx->current_header_index); if (header_handle < 0) { error_setg( @@ -187,7 +188,7 @@ static int qigvm_handler(QIgvm *ctx, IgvmVariableHeader= Type raw_type, (int)header_handle); return -1; } - header_data =3D igvm_get_buffer(ctx->file, header_handle); + header_data =3D igvm_get_buffer(ctx->cfg->file, header_handle); if (header_data !=3D NULL) { header_data +=3D sizeof(IGVM_VHS_VARIABLE_HEADER); result =3D handlers[handler].handler(ctx, header_data, errp); @@ -198,7 +199,7 @@ static int qigvm_handler(QIgvm *ctx, IgvmVariableHeader= Type raw_type, header_handle, type); result =3D -1; } - igvm_free_buffer(ctx->file, header_handle); + igvm_free_buffer(ctx->cfg->file, header_handle); return result; } =20 @@ -344,7 +345,8 @@ static int qigvm_process_mem_region(QIgvm *ctx, unsigne= d start_index, =20 for (page_index =3D 0; page_index < page_count; page_index++) { data_handle =3D igvm_get_header_data( - ctx->file, IGVM_HEADER_SECTION_DIRECTIVE, page_index + start_i= ndex); + ctx->cfg->file, IGVM_HEADER_SECTION_DIRECTIVE, + page_index + start_index); if (data_handle =3D=3D IGVMAPI_NO_DATA) { /* No data indicates a zero page */ memset(®ion[page_index * page_size], 0, page_size); @@ -357,7 +359,7 @@ static int qigvm_process_mem_region(QIgvm *ctx, unsigne= d start_index, return -1; } else { zero =3D false; - data_size =3D igvm_get_buffer_size(ctx->file, data_handle); + data_size =3D igvm_get_buffer_size(ctx->cfg->file, data_handle= ); if (data_size < page_size) { memset(®ion[page_index * page_size], 0, page_size); } else if (data_size > page_size) { @@ -367,14 +369,14 @@ static int qigvm_process_mem_region(QIgvm *ctx, unsig= ned start_index, page_index + start_index); return -1; } - data =3D igvm_get_buffer(ctx->file, data_handle); + data =3D igvm_get_buffer(ctx->cfg->file, data_handle); if (data =3D=3D NULL) { error_setg(errp, "IGVM: No buffer for handle %d", data_han= dle); - igvm_free_buffer(ctx->file, data_handle); + igvm_free_buffer(ctx->cfg->file, data_handle); return -1; } memcpy(®ion[page_index * page_size], data, data_size); - igvm_free_buffer(ctx->file, data_handle); + igvm_free_buffer(ctx->cfg->file, data_handle); } } =20 @@ -411,7 +413,8 @@ static int qigvm_process_mem_page(QIgvm *ctx, ctx->region_start =3D page_data->gpa; ctx->region_start_index =3D ctx->current_header_index; } else { - if (!qigvm_page_attrs_equal(ctx->file, ctx->current_header_ind= ex, + if (!qigvm_page_attrs_equal(ctx->cfg->file, + ctx->current_header_index, page_data, &ctx->region_prev_page_data) || ((ctx->region_prev_page_data.gpa + @@ -474,7 +477,8 @@ static int qigvm_directive_vp_context(QIgvm *ctx, const= uint8_t *header_data, return 0; } =20 - data_handle =3D igvm_get_header_data(ctx->file, IGVM_HEADER_SECTION_DI= RECTIVE, + data_handle =3D igvm_get_header_data(ctx->cfg->file, + IGVM_HEADER_SECTION_DIRECTIVE, ctx->current_header_index); if (data_handle < 0) { error_setg(errp, "Invalid VP context in IGVM file. Error code: %X", @@ -482,7 +486,7 @@ static int qigvm_directive_vp_context(QIgvm *ctx, const= uint8_t *header_data, return -1; } =20 - data =3D (uint8_t *)igvm_get_buffer(ctx->file, data_handle); + data =3D (uint8_t *)igvm_get_buffer(ctx->cfg->file, data_handle); if (data =3D=3D NULL) { error_setg(errp, "IGVM: No buffer for handle %d", data_handle); result =3D -1; @@ -491,7 +495,8 @@ static int qigvm_directive_vp_context(QIgvm *ctx, const= uint8_t *header_data, =20 if (ctx->machine_state->cgs) { result =3D ctx->cgsc->set_guest_state( - vp_context->gpa, data, igvm_get_buffer_size(ctx->file, data_ha= ndle), + vp_context->gpa, data, + igvm_get_buffer_size(ctx->cfg->file, data_handle), CGS_PAGE_TYPE_VMSA, vp_context->vp_index, errp); } else if (target_arch() =3D=3D SYS_EMU_TARGET_X86_64) { result =3D qigvm_x86_set_vp_context(data, vp_context->vp_index, er= rp); @@ -504,7 +509,7 @@ static int qigvm_directive_vp_context(QIgvm *ctx, const= uint8_t *header_data, } =20 exit: - igvm_free_buffer(ctx->file, data_handle); + igvm_free_buffer(ctx->cfg->file, data_handle); if (result < 0) { return result; } @@ -863,7 +868,8 @@ static int qigvm_supported_platform_compat_mask(QIgvm *= ctx, Error **errp) uint32_t compatibility_mask_sev_snp =3D 0; uint32_t compatibility_mask =3D 0; =20 - header_count =3D igvm_header_count(ctx->file, IGVM_HEADER_SECTION_PLAT= FORM); + header_count =3D igvm_header_count(ctx->cfg->file, + IGVM_HEADER_SECTION_PLATFORM); if (header_count < 0) { error_setg(errp, "Invalid platform header count in IGVM file. Error code= : %X", @@ -874,11 +880,11 @@ static int qigvm_supported_platform_compat_mask(QIgvm= *ctx, Error **errp) for (header_index =3D 0; header_index < (unsigned)header_count; header_index++) { IgvmVariableHeaderType typ =3D igvm_get_header_type( - ctx->file, IGVM_HEADER_SECTION_PLATFORM, header_index); + ctx->cfg->file, IGVM_HEADER_SECTION_PLATFORM, header_index); typ =3D igvm_vht_type(typ); if (typ =3D=3D IGVM_VHT_SUPPORTED_PLATFORM) { header_handle =3D igvm_get_header( - ctx->file, IGVM_HEADER_SECTION_PLATFORM, header_index); + ctx->cfg->file, IGVM_HEADER_SECTION_PLATFORM, header_index= ); if (header_handle < 0) { error_setg(errp, "Invalid platform header in IGVM file. " @@ -887,11 +893,11 @@ static int qigvm_supported_platform_compat_mask(QIgvm= *ctx, Error **errp) return -1; } platform =3D - (IGVM_VHS_SUPPORTED_PLATFORM *)(igvm_get_buffer(ctx->file, + (IGVM_VHS_SUPPORTED_PLATFORM *)(igvm_get_buffer(ctx->cfg->= file, header_han= dle)); if (platform =3D=3D NULL) { error_setg(errp, "IGVM: No buffer for handle %d", header_h= andle); - igvm_free_buffer(ctx->file, header_handle); + igvm_free_buffer(ctx->cfg->file, header_handle); return -1; } =20 @@ -922,7 +928,7 @@ static int qigvm_supported_platform_compat_mask(QIgvm *= ctx, Error **errp) } else if (platform->platform_type =3D=3D IGVM_PLATFORM_TYPE_N= ATIVE) { compatibility_mask =3D platform->compatibility_mask; } - igvm_free_buffer(ctx->file, header_handle); + igvm_free_buffer(ctx->cfg->file, header_handle); } } /* Choose the strongest supported isolation technology */ @@ -999,7 +1005,7 @@ int qigvm_process_file(IgvmCfg *cfg, MachineState *mac= hine_state, error_setg(errp, "No IGVM file loaded."); return -1; } - ctx.file =3D cfg->file; + ctx.cfg =3D cfg; trace_igvm_process_file(cfg->file, onlyVpContext); =20 ctx.machine_state =3D machine_state; @@ -1021,7 +1027,8 @@ int qigvm_process_file(IgvmCfg *cfg, MachineState *ma= chine_state, goto cleanup; } =20 - header_count =3D igvm_header_count(ctx.file, IGVM_HEADER_SECTION_DIREC= TIVE); + header_count =3D igvm_header_count(ctx.cfg->file, + IGVM_HEADER_SECTION_DIRECTIVE); if (header_count <=3D 0) { error_setg( errp, "Invalid directive header count in IGVM file. Error code= : %X", @@ -1035,7 +1042,8 @@ int qigvm_process_file(IgvmCfg *cfg, MachineState *ma= chine_state, ctx.current_header_index < (unsigned)header_count; ctx.current_header_index++) { IgvmVariableHeaderType raw_type =3D igvm_get_header_type( - ctx.file, IGVM_HEADER_SECTION_DIRECTIVE, ctx.current_header_in= dex); + ctx.cfg->file, IGVM_HEADER_SECTION_DIRECTIVE, + ctx.current_header_index); if (!onlyVpContext || igvm_vht_type(raw_type) =3D=3D IGVM_VHT_VP_C= ONTEXT) { if (qigvm_handler(&ctx, raw_type, errp) < 0) { goto cleanup_parameters; @@ -1053,7 +1061,7 @@ int qigvm_process_file(IgvmCfg *cfg, MachineState *ma= chine_state, } =20 header_count =3D - igvm_header_count(ctx.file, IGVM_HEADER_SECTION_INITIALIZATION); + igvm_header_count(ctx.cfg->file, IGVM_HEADER_SECTION_INITIALIZATIO= N); if (header_count < 0) { error_setg( errp, @@ -1066,7 +1074,8 @@ int qigvm_process_file(IgvmCfg *cfg, MachineState *ma= chine_state, ctx.current_header_index < (unsigned)header_count; ctx.current_header_index++) { IgvmVariableHeaderType type =3D - igvm_get_header_type(ctx.file, IGVM_HEADER_SECTION_INITIALIZAT= ION, + igvm_get_header_type(ctx.cfg->file, + IGVM_HEADER_SECTION_INITIALIZATION, ctx.current_header_index); if (qigvm_handler(&ctx, type, errp) < 0) { goto cleanup_parameters; --=20 2.55.0 From nobody Fri Aug 21 21:27:09 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1787328708; cv=none; d=zohomail.com; s=zohoarc; b=dm0jfQP/l+tAUYKNFoxxZhZdVgIOSJuGH+uz+miZuUEnXZ2d3PlduXqCFh59+INJHgOY85NRA5jEnL0ZM3WpPx8LxphegUPCWcP3Tx05YL8IQP/l6cG7H40D2mGb19nqBZaWzmGM9swqF1RxVHAuOoO5WwgCkhjnNVonYHhDgio= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787328708; 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=YEeZJYKJX1xIk+QWnsyka0rk9xsQ+a9ce5gIMMhuxXw=; b=UUaXR1WcaGRBJfyLl9crW/lMgdfiei9LbLLjfvr3UQ5CaIgI0Q7aJJP7ZwaUAJg1VokugrWYBTrSjKpKGxYt2qS6h5c9U5QH+wG7Z430dJYiflUejDS/pm4co/txLh1T6tl7uKWWkYYBoSvjthdfU96CIqUceWUfZTAHfxvzIO0= 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=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787328708805597.9582205329388; Fri, 21 Aug 2026 09:11:48 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wxRpw-0006X1-W7; Fri, 21 Aug 2026 12:11:21 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRpu-0006VY-Qh for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:18 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRps-0001Yn-Kg for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:18 -0400 Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-645-NKOqdrIyOQi6eniOXrIwPQ-1; Fri, 21 Aug 2026 12:11:09 -0400 Received: from mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.95]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 17E761953993; Fri, 21 Aug 2026 16:11:08 +0000 (UTC) Received: from sirius.home.kraxel.org (unknown [10.44.48.30]) by mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id D2B297D9; Fri, 21 Aug 2026 16:11:06 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 7845C1800795; Fri, 21 Aug 2026 18:11:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787328676; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=YEeZJYKJX1xIk+QWnsyka0rk9xsQ+a9ce5gIMMhuxXw=; b=SmGgXLx7yrylSvWpeMiJqjBQuxN+Hk1vzWhHTJCTv1KQNT2DLmO+ZU5otGIMmla3Eh/Nlj hSjeMc3WqNKmXI4YjqJv7w6fXsEVDGeUq73Qe7Qpi1ca0zNq1y/Iix0pj1W6imav9z5KSI LeZTKIAIv7RY3m/WoTN+GvPln2eDcx8= X-MC-Unique: NKOqdrIyOQi6eniOXrIwPQ-1 X-Mimecast-MFC-AGG-ID: NKOqdrIyOQi6eniOXrIwPQ_1787328668 From: Gerd Hoffmann To: qemu-devel@nongnu.org Cc: Ani Sinha , Cornelia Huck , Peter Maydell , Zhao Liu , Peter Xu , qemu-arm@nongnu.org, Pierrick Bouvier , Gerd Hoffman , "Michael S. Tsirkin" , Stefano Garzarella , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Laurent Vivier , Fabiano Rosas , Paolo Bonzini , Alexander Graf Subject: [PULL 03/12] igvm: track memory regions Date: Fri, 21 Aug 2026 18:10:51 +0200 Message-ID: <20260821161103.3489298-4-kraxel@redhat.com> In-Reply-To: <20260821161103.3489298-1-kraxel@redhat.com> References: <20260821161103.3489298-1-kraxel@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.6 on 10.30.177.95 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=lists1p.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 9 X-Spam_score: 0.9 X-Spam_bar: / X-Spam_report: (0.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.341, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=0.001, RCVD_IN_SBL_CSS=3.335, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action 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 @redhat.com) X-ZM-MESSAGEID: 1787328711178158500 Content-Type: text/plain; charset="utf-8" Memory regions added by the current IGVM needs to be tracked so that they c= an be freed when a new IGVM is loaded. Reviewed-by: Ani Sinha Reviewed-by: Alexander Graf Signed-off-by: Gerd Hoffmann Message-ID: <20260817142010.80693-3-anisinha@redhat.com> Signed-off-by: Gerd Hoffmann --- include/system/igvm-internal.h | 6 ++++++ backends/igvm-cfg.c | 1 + backends/igvm.c | 20 ++++++++++++-------- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/include/system/igvm-internal.h b/include/system/igvm-internal.h index b5720fae0c00..9e9fa1d9afdb 100644 --- a/include/system/igvm-internal.h +++ b/include/system/igvm-internal.h @@ -18,6 +18,11 @@ #include "system/confidential-guest-support.h" #include =20 +typedef struct IgvmMemoryRegion { + QTAILQ_ENTRY(IgvmMemoryRegion) next; + MemoryRegion *mr; +} IgvmMemoryRegion; + struct IgvmCfg { Object parent_obj; =20 @@ -29,6 +34,7 @@ struct IgvmCfg { char *filename; IgvmHandle file; ResettableState reset_state; + QTAILQ_HEAD(, IgvmMemoryRegion) memory_regions; }; =20 typedef struct QIgvmParameterData { diff --git a/backends/igvm-cfg.c b/backends/igvm-cfg.c index e1f09855f66d..38438a7b1e2c 100644 --- a/backends/igvm-cfg.c +++ b/backends/igvm-cfg.c @@ -65,6 +65,7 @@ static void igvm_complete(UserCreatable *uc, Error **errp) IgvmCfg *igvm =3D IGVM_CFG(uc); =20 igvm->file =3D qigvm_file_init(igvm->filename, errp); + QTAILQ_INIT(&igvm->memory_regions); } =20 OBJECT_DEFINE_TYPE_WITH_INTERFACES(IgvmCfg, igvm_cfg, IGVM_CFG, OBJECT, diff --git a/backends/igvm.c b/backends/igvm.c index 534032fed812..9e7c90d386d1 100644 --- a/backends/igvm.c +++ b/backends/igvm.c @@ -220,7 +220,7 @@ static void *qigvm_prepare_memory(QIgvm *ctx, uint64_t = addr, uint64_t size, int region_identifier, Error **errp) { ERRP_GUARD(); - MemoryRegion *igvm_pages =3D NULL; + IgvmMemoryRegion *imr =3D NULL; Int128 gpa_region_size; MemoryRegionSection mrs =3D memory_region_find(get_system_memory(), addr, size); @@ -254,23 +254,27 @@ static void *qigvm_prepare_memory(QIgvm *ctx, uint64_= t addr, uint64_t size, */ g_autofree char *region_name =3D g_strdup_printf("igvm.%X", region_identifier); - igvm_pages =3D g_new0(MemoryRegion, 1); + imr =3D g_new0(IgvmMemoryRegion, 1); + imr->mr =3D g_new0(MemoryRegion, 1); if (ctx->machine_state->cgs && ctx->machine_state->cgs->require_guest_memfd) { - if (!memory_region_init_ram_guest_memfd(igvm_pages, NULL, + if (!memory_region_init_ram_guest_memfd(imr->mr, NULL, region_name, size, err= p)) { - g_free(igvm_pages); + g_free(imr->mr); + g_free(imr); return NULL; } } else { - if (!memory_region_init_ram(igvm_pages, NULL, region_name, siz= e, + if (!memory_region_init_ram(imr->mr, NULL, region_name, size, errp)) { - g_free(igvm_pages); + g_free(imr->mr); + g_free(imr); return NULL; } } - memory_region_add_subregion(get_system_memory(), addr, igvm_pages); - return memory_region_get_ram_ptr(igvm_pages); + memory_region_add_subregion(get_system_memory(), addr, imr->mr); + QTAILQ_INSERT_TAIL(&ctx->cfg->memory_regions, imr, next); + return memory_region_get_ram_ptr(imr->mr); } } =20 --=20 2.55.0 From nobody Fri Aug 21 21:27:09 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1787328777; cv=none; d=zohomail.com; s=zohoarc; b=jo01pwTdLJ059L677ZmTFk5Tp+8q4XHjlpq39Jh4I+Z1Gwg6H+ZZCJSA/Tdp/uFpmN4boKUNHlueG6DBA/y/LGbpTBivJivE5se5NoMjbZxgMplfDLATN0WTKo0/Cm8UZzShK3jbxfCjADBxN/XcbrNE0FGbAupoRPQbpENyUSE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787328777; 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=hTsrtmm6zAVtEaNueaYmf+4CzykffyTMsO6iRQfbyEM=; b=cfth8lnkMO0o+KOHlZ85XQBPi0dgoZjXHcsT8Bj9FO1SWokiU3W6owLOcGHyqTSZ6dLZL6ZQ9xLy5iB+hu0t8YXA+3Cyj9P2KqO6l8fd8s4tF//NagC0y3AF4tBpzgLhAkrX6ik0IA9ES9O5GsryydbU8MmWeQmtPPSZEssoIV0= 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=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787328777779708.0778572879178; Fri, 21 Aug 2026 09:12:57 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wxRq0-0006Zj-MH; Fri, 21 Aug 2026 12:11:24 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRpy-0006Y3-ES for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:22 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRpx-0001aZ-0i for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:22 -0400 Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-156-3h5JWwRsOZqdJcVhr2V9Vw-1; Fri, 21 Aug 2026 12:11:11 -0400 Received: from mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.95]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E59F31954B20; Fri, 21 Aug 2026 16:11:08 +0000 (UTC) Received: from sirius.home.kraxel.org (unknown [10.44.48.30]) by mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 9743C7D6; Fri, 21 Aug 2026 16:11:08 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 9282618007A3; Fri, 21 Aug 2026 18:11:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787328680; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hTsrtmm6zAVtEaNueaYmf+4CzykffyTMsO6iRQfbyEM=; b=OpaPW5Chn+4+r2+z8OpwuBPej0oOXhyaQIQtPwfSaPPxjwx3munNm9VpkuOPdKDo56BZRh ZONTEOokFKcqNnfTy2BHmFHOvfFOmjnhY7Td2gO0NAOOFprGHL5BeuIqW1pYkSYOkfikAt IcFnZdM6qYsz6x/9s8jSCvLxm3bCscU= X-MC-Unique: 3h5JWwRsOZqdJcVhr2V9Vw-1 X-Mimecast-MFC-AGG-ID: 3h5JWwRsOZqdJcVhr2V9Vw_1787328669 From: Gerd Hoffmann To: qemu-devel@nongnu.org Cc: Ani Sinha , Cornelia Huck , Peter Maydell , Zhao Liu , Peter Xu , qemu-arm@nongnu.org, Pierrick Bouvier , Gerd Hoffman , "Michael S. Tsirkin" , Stefano Garzarella , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Laurent Vivier , Fabiano Rosas , Paolo Bonzini , Alexander Graf Subject: [PULL 04/12] igvm: cleanup memory regions Date: Fri, 21 Aug 2026 18:10:52 +0200 Message-ID: <20260821161103.3489298-5-kraxel@redhat.com> In-Reply-To: <20260821161103.3489298-1-kraxel@redhat.com> References: <20260821161103.3489298-1-kraxel@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.6 on 10.30.177.95 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=lists1p.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 9 X-Spam_score: 0.9 X-Spam_bar: / X-Spam_report: (0.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.341, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_SBL_CSS=3.335, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action 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 @redhat.com) X-ZM-MESSAGEID: 1787328780460158500 Content-Type: text/plain; charset="utf-8" This change cleans up existing memory regions that were created by the curr= ent IGVM. The cleanup would be necessary when a new IGVM is loaded. This cleanup function is called in a subsequent patch. Reviewed-by: Alexander Graf Tested-by: Ani Sinha Signed-off-by: Gerd Hoffmann Message-ID: <20260817142010.80693-4-anisinha@redhat.com> Signed-off-by: Gerd Hoffmann --- include/system/igvm.h | 1 + backends/igvm-cfg.c | 2 ++ backends/igvm.c | 19 +++++++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/include/system/igvm.h b/include/system/igvm.h index 64d3542311ae..e219f1a4edb4 100644 --- a/include/system/igvm.h +++ b/include/system/igvm.h @@ -20,6 +20,7 @@ typedef struct QIgvm QIgvm; =20 int qigvm_process_file(IgvmCfg *igvm, MachineState *machine_state, bool onlyVpContext, Error **errp); +void qigvm_cleanup_memory(IgvmCfg *igvm); =20 /* x86 native */ int qigvm_x86_get_mem_map_entry(int index, diff --git a/backends/igvm-cfg.c b/backends/igvm-cfg.c index 38438a7b1e2c..935ba54f54f3 100644 --- a/backends/igvm-cfg.c +++ b/backends/igvm-cfg.c @@ -52,6 +52,8 @@ static void igvm_reset_hold(Object *obj, ResetType type) =20 trace_igvm_reset_hold(type); =20 + /* cleanup existing memory regions first */ + qigvm_cleanup_memory(igvm); qigvm_process_file(igvm, ms, false, &error_fatal); } =20 diff --git a/backends/igvm.c b/backends/igvm.c index 9e7c90d386d1..9b101c81824e 100644 --- a/backends/igvm.c +++ b/backends/igvm.c @@ -14,6 +14,7 @@ #include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/target-info-qapi.h" +#include "migration/vmstate.h" #include "system/igvm.h" #include "system/igvm-cfg.h" #include "system/igvm-internal.h" @@ -1109,3 +1110,21 @@ cleanup_parameters: cleanup: return retval; } + +/* + * cleanup any memory regions created by qigvm_prepare_memory() + */ +void qigvm_cleanup_memory(IgvmCfg *cfg) +{ + IgvmMemoryRegion *imr, *tmp; + + QTAILQ_FOREACH_SAFE(imr, &cfg->memory_regions, next, tmp) + { + memory_region_del_subregion(get_system_memory(), imr->mr); + vmstate_unregister_ram(imr->mr, NULL); + QTAILQ_REMOVE(&cfg->memory_regions, imr, next); + /* this triggers MemoryRegion cleanup */ + object_unparent(OBJECT(imr->mr)); + g_free(imr); + } +} --=20 2.55.0 From nobody Fri Aug 21 21:27:09 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1787328757; cv=none; d=zohomail.com; s=zohoarc; b=lA0AT2JQGlhPaxkgURRps4P1b9sc0LABsxLCYAHRts/HVG5pd6hVPVwT/3ke6zohv38GaBoWu+zO3tPDH+7FZCvndyJIzC0N1QJr48kO5cHGh62A6j3HuqiJiOCV6LxL6zEWu79Di+8qbtW1eyYmLENxHrgoIvXG4DkE8GFBE1w= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787328757; 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=D1gm7XVbBrfW/CNzKmnwPXas9oKKJdliXnnrqJ/5pcw=; b=YAT7TD9hq83njdBelrlpknGIyqjouKWYmRocyhUtUjsoKnRAHDtNg62OUG2xMr9h4ImnzAE+ZyvxDs9e847QtQRNJOlgE9rg3VGjv9TgY1HzAefV0Nie6LNdp6yRdiIMPjGHphSovw4+eEYg46n+7XaaSF5aOKxp8ClnB9cOeEE= 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=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787328757071404.05120489385024; Fri, 21 Aug 2026 09:12:37 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wxRpv-0006Vl-2R; Fri, 21 Aug 2026 12:11:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRpt-0006Ud-FC for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:17 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRpr-0001YD-VK for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:17 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-561-JhwlavFdPKCODAWUhGDaHg-1; Fri, 21 Aug 2026 12:11:11 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 51CD51802143; Fri, 21 Aug 2026 16:11:09 +0000 (UTC) Received: from sirius.home.kraxel.org (unknown [10.44.48.30]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 9759F18005BD; Fri, 21 Aug 2026 16:11:08 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id A4971180086B; Fri, 21 Aug 2026 18:11:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787328675; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=D1gm7XVbBrfW/CNzKmnwPXas9oKKJdliXnnrqJ/5pcw=; b=iF9WpSDOMY2iF79v7tWj1o29HjT4goC8Ywxx80ia9rFGi9OqlGhTdC1xAPZ4nCJx19XNwu NAng1P/xTYsyBLfQQ3XQAXZaLRqycJ+GtcQ8B1JCpyopaR+2lQSFO5NsmykYGRFPip9TVl OvqG85MrlvQGSecxYJqzyQKOG/LPufk= X-MC-Unique: JhwlavFdPKCODAWUhGDaHg-1 X-Mimecast-MFC-AGG-ID: JhwlavFdPKCODAWUhGDaHg_1787328669 From: Gerd Hoffmann To: qemu-devel@nongnu.org Cc: Ani Sinha , Cornelia Huck , Peter Maydell , Zhao Liu , Peter Xu , qemu-arm@nongnu.org, Pierrick Bouvier , Gerd Hoffman , "Michael S. Tsirkin" , Stefano Garzarella , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Laurent Vivier , Fabiano Rosas , Paolo Bonzini Subject: [PULL 05/12] system/memory: add a tracepoint for memory_region_finalize Date: Fri, 21 Aug 2026 18:10:53 +0200 Message-ID: <20260821161103.3489298-6-kraxel@redhat.com> In-Reply-To: <20260821161103.3489298-1-kraxel@redhat.com> References: <20260821161103.3489298-1-kraxel@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 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=lists1p.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -23 X-Spam_score: -2.4 X-Spam_bar: -- X-Spam_report: (-2.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.341, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action 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 @redhat.com) X-ZM-MESSAGEID: 1787328760439158500 Content-Type: text/plain; charset="utf-8" From: Ani Sinha cosmetic: add a tracepoint to track when memory regions are getting freed. Useful for debugging and tracking all freed memory regions. Reviewed-by: Peter Xu Signed-off-by: Ani Sinha Message-ID: <20260817142010.80693-5-anisinha@redhat.com> Signed-off-by: Gerd Hoffmann --- system/memory.c | 1 + system/trace-events | 1 + 2 files changed, 2 insertions(+) diff --git a/system/memory.c b/system/memory.c index da710bbade1b..9760721e4550 100644 --- a/system/memory.c +++ b/system/memory.c @@ -1691,6 +1691,7 @@ static void memory_region_finalize(Object *obj) { MemoryRegion *mr =3D MEMORY_REGION(obj); =20 + trace_memory_region_finalize(mr->name); /* * Each memory region (that can be freed) must have an owner, and it * always has the same lifecycle of its owner. It means when reaching diff --git a/system/trace-events b/system/trace-events index d483b31419bc..38ad0be8a998 100644 --- a/system/trace-events +++ b/system/trace-events @@ -25,6 +25,7 @@ flatview_new(void *view, void *root) "%p (root %p)" flatview_destroy(void *view, void *root) "%p (root %p)" flatview_destroy_rcu(void *view, void *root) "%p (root %p)" global_dirty_changed(unsigned int bitmask) "bitmask 0x%"PRIx32 +memory_region_finalize(const char* name) "mr %s" =20 # physmem.c address_space_map(void *as, uint64_t addr, uint64_t len, bool is_write, ui= nt32_t attrs) "as:%p addr 0x%"PRIx64":%"PRIx64" write:%d attrs:0x%x" --=20 2.55.0 From nobody Fri Aug 21 21:27:09 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1787328784; cv=none; d=zohomail.com; s=zohoarc; b=Kw14cSeENlepdJcCWdLImmNJnvFURs8w5JP4iOGYm68yWOhJOERacrwzJAu1/KZz3O/jSVnEUcJCOT8E2dnyy1ClreAVRbmLaf0t1G1gkFqTJjEye1RfOx0wuujlTlCQqYmlJJNzBsQP/6qNYTO06CwQd9/MC5K21dwB4Lp8WQs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787328784; 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=Zdltyd2KdCMXu+fgkLkbV6vgW6gMOcE7mbXXQPuJ/8A=; b=PZwDTFwLu8pqq+oA9tvcEGcCdzfKEPlAKelloEQCAH0nTsk8Cvo1KtiZ+uLbiLSjhVfrY7IztyScv6bSsIfCxYAqAe7hRGZDMdvd3ABJZWJVaV1AqTOacpuB9C+ml9cr1tNoP4xlY0vml21SOCmqpgq1GEz/8me315bs9P18v64= 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=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787328784448532.3154426613364; Fri, 21 Aug 2026 09:13:04 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wxRq8-0006ct-IG; Fri, 21 Aug 2026 12:11:34 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRq3-0006b5-7d for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:27 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRq1-0001bo-An for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:26 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-625--RqN4dEPNn21cyERIghkpg-1; Fri, 21 Aug 2026 12:11:11 -0400 Received: from mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.95]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id CDD591801332; Fri, 21 Aug 2026 16:11:09 +0000 (UTC) Received: from sirius.home.kraxel.org (unknown [10.44.48.30]) by mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 63EA9426; Fri, 21 Aug 2026 16:11:09 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id B643C18009E1; Fri, 21 Aug 2026 18:11:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787328684; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Zdltyd2KdCMXu+fgkLkbV6vgW6gMOcE7mbXXQPuJ/8A=; b=Y6OO20zn3iBQZJfC+t1MD+TzyRB7+nI6UtDUetYsCmv9sptH/kgaHTFYZnWpwgfDp74wQS ij25HrFq8AZn9oia9MoAMIQV2x4pS98Gjafa6Sq+GVZoQ/TvMQ3HfFxS/LfKDl92/Zt59s wo9RWfKM7r1qIc5SCDHUPITBlDLNgWw= X-MC-Unique: -RqN4dEPNn21cyERIghkpg-1 X-Mimecast-MFC-AGG-ID: -RqN4dEPNn21cyERIghkpg_1787328669 From: Gerd Hoffmann To: qemu-devel@nongnu.org Cc: Ani Sinha , Cornelia Huck , Peter Maydell , Zhao Liu , Peter Xu , qemu-arm@nongnu.org, Pierrick Bouvier , Gerd Hoffman , "Michael S. Tsirkin" , Stefano Garzarella , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Laurent Vivier , Fabiano Rosas , Paolo Bonzini Subject: [PULL 06/12] backends/igvm: add a tracepoint for qigvm_cleanup_memory Date: Fri, 21 Aug 2026 18:10:54 +0200 Message-ID: <20260821161103.3489298-7-kraxel@redhat.com> In-Reply-To: <20260821161103.3489298-1-kraxel@redhat.com> References: <20260821161103.3489298-1-kraxel@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.6 on 10.30.177.95 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=lists1p.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -23 X-Spam_score: -2.4 X-Spam_bar: -- X-Spam_report: (-2.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.341, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action 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 @redhat.com) X-ZM-MESSAGEID: 1787328786126158500 Content-Type: text/plain; charset="utf-8" From: Ani Sinha Useful for debugging memory region cleanups. Signed-off-by: Ani Sinha Message-ID: <20260817142010.80693-6-anisinha@redhat.com> Signed-off-by: Gerd Hoffmann --- backends/igvm.c | 1 + backends/trace-events | 1 + 2 files changed, 2 insertions(+) diff --git a/backends/igvm.c b/backends/igvm.c index 9b101c81824e..7b7bdc72b75b 100644 --- a/backends/igvm.c +++ b/backends/igvm.c @@ -1120,6 +1120,7 @@ void qigvm_cleanup_memory(IgvmCfg *cfg) =20 QTAILQ_FOREACH_SAFE(imr, &cfg->memory_regions, next, tmp) { + trace_qigvm_cleanup_memory(imr->mr->name); memory_region_del_subregion(get_system_memory(), imr->mr); vmstate_unregister_ram(imr->mr, NULL); QTAILQ_REMOVE(&cfg->memory_regions, imr, next); diff --git a/backends/trace-events b/backends/trace-events index 009a25b0be96..9b7b9b7d6801 100644 --- a/backends/trace-events +++ b/backends/trace-events @@ -33,3 +33,4 @@ igvm_reset_hold(int type) "type=3D%u" igvm_reset_exit(int type) "type=3D%u" igvm_file_loaded(const char *fn, int32_t handle) "fn=3D%s, handle=3D0x%x" igvm_process_file(int32_t handle, bool context_only) "handle=3D0x%x contex= t-only=3D%d" +qigvm_cleanup_memory(const char* name) "freeing mr %s" --=20 2.55.0 From nobody Fri Aug 21 21:27:09 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1787328797; cv=none; d=zohomail.com; s=zohoarc; b=j6kOUOlcwe9x7bKE14CDMKFVJqSI58foyR1OU9xHdHvbPVcmJM0ziqkibkjCl4h9W9tMssJZyqO/VDA/KzHCMaPmDLwySs+vtqFlCRn3TOrJ6YBgKHLRf/gYuu01yHfrsUSGD1mpI+6zFkNF1RO5tYMA7YLKZ/gTx6rYXnqQ2WM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787328797; 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=UHHbXCFXSIBwhZO+RcdwANDP52+6cNIBxovkI1SsLo8=; b=RGJGHkUcLyU7KV0zrqdgSOv6ZLGHkyOpyr1CxmwM97pTwm+4Fg81HmcqpiDLMyi/Mx/sTidAo68kbiqx/gvuz6HfowWIjT5BDbVMWxYq3oZ01QVhyHCHzl99Tp4k+0aXf4AHfiyQX9ASQdEFOyBY5udBJyWuKKFE48SZHeikIVo= 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=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787328797289619.1722289485161; Fri, 21 Aug 2026 09:13:17 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wxRpy-0006Xs-43; Fri, 21 Aug 2026 12:11:22 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRpu-0006Vd-TL for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:18 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRps-0001Yw-Mz for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:18 -0400 Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-522-XbiGUgXYNBa9VbvfCnYJHQ-1; Fri, 21 Aug 2026 12:11:11 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 186E61953985; Fri, 21 Aug 2026 16:11:10 +0000 (UTC) Received: from sirius.home.kraxel.org (unknown [10.44.48.30]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C54401800257; Fri, 21 Aug 2026 16:11:09 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id C6E9D1800D49; Fri, 21 Aug 2026 18:11:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787328676; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UHHbXCFXSIBwhZO+RcdwANDP52+6cNIBxovkI1SsLo8=; b=NX4o5MzUed3Ynn/V8LB1x5CmmtTJubmHwfVoKmcNeRljmI0aEJH/iDZ1OqAXKsAxrAXZhS 2P7R870cUOKTYDZlth0FVH+FdTzx0n3AL4LBXTVQtZDKU7WrCqXiLJmIsCd2Nezb15XP6k qivL6ZCGJ/gv9xWMztVZurk27vX+fGs= X-MC-Unique: XbiGUgXYNBa9VbvfCnYJHQ-1 X-Mimecast-MFC-AGG-ID: XbiGUgXYNBa9VbvfCnYJHQ_1787328670 From: Gerd Hoffmann To: qemu-devel@nongnu.org Cc: Ani Sinha , Cornelia Huck , Peter Maydell , Zhao Liu , Peter Xu , qemu-arm@nongnu.org, Pierrick Bouvier , Gerd Hoffman , "Michael S. Tsirkin" , Stefano Garzarella , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Laurent Vivier , Fabiano Rosas , Paolo Bonzini , Alex Graf Subject: [PULL 07/12] hw/misc/vmlaunchupdate: add api header Date: Fri, 21 Aug 2026 18:10:55 +0200 Message-ID: <20260821161103.3489298-8-kraxel@redhat.com> In-Reply-To: <20260821161103.3489298-1-kraxel@redhat.com> References: <20260821161103.3489298-1-kraxel@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 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=lists1p.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 9 X-Spam_score: 0.9 X-Spam_bar: / X-Spam_report: (0.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.341, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_SBL_CSS=3.335, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action 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 @redhat.com) X-ZM-MESSAGEID: 1787328798265158500 Content-Type: text/plain; charset="utf-8" From: Ani Sinha Add a separate header file for guest usable api definitions. CC: Alex Graf CC: Gerd Hoffman Reviewed-by: Alexander Graf Signed-off-by: Ani Sinha Message-ID: <20260819041105.110625-1-anisinha@redhat.com> Signed-off-by: Gerd Hoffmann --- .../standard-headers/misc/vmlaunchupdate.h | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 include/standard-headers/misc/vmlaunchupdate.h diff --git a/include/standard-headers/misc/vmlaunchupdate.h b/include/stand= ard-headers/misc/vmlaunchupdate.h new file mode 100644 index 000000000000..7f8382a765d1 --- /dev/null +++ b/include/standard-headers/misc/vmlaunchupdate.h @@ -0,0 +1,102 @@ +/* + * Guest driven VM launch state update device via IGVM. + * The definitions in this header defines the API for the hypervisor inter= face. + * For details and specification, please look at docs/specs/vmlaunchupdate= .rst. + * + * Copyright (C) 2026 Red Hat, Inc. + * + * Authors: Ani Sinha + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + */ +#ifndef VMLAUNCHUPDATE_API_H +#define VMLAUNCHUPDATE_API_H + +/* fw-cfg file definition */ +#define FILE_VMLAUNCHUPDATE "etc/vmlaunchupdate" + +/* version */ +#define VM_LAUNCHUPDATE_VERSION 0x01 + +/* format bits, used by both 'capabilities' and 'control' */ + +/* igvm */ +#define VM_LAUNCHUPDATE_FORMAT_IGVM (1ULL << 32) + +/* 'control' field bits */ + +/* disable vmlaunchupdate interface */ +#define VM_LAUNCHUPDATE_CTL_DISABLE (1 << 0) +/* revert to the original host provided igvm */ +#define VM_LAUNCHUPDATE_CTL_HOST_IGVM (1 << 1) + +/* The combination of the above two ctl interfaces work as + * follows: + * + * A) CTL_HOST_IGVM=3Doff CTL_DISABLE=3Doff + * + * Supplied IGVM file replaces the firmware permanently. Updating the + * firmware again is possible. + * + * B) CTL_HOST_IGVM=3Doff CTL_DISABLE=3Don + * + * Supplied IGVM file replaces the firmware permanently. Updating the + * firmware again is not possible. + * + * C) CTL_HOST_IGVM=3Don CTL_DISABLE=3Doff + * + * Supplied IGVM file replaces the firmware for one reset. Resetting + * again will switch back to the original firmware. Updating the + * firmware again is possible. + * + * D) CTL_HOST_IGVM=3Don CTL_DISABLE=3Don + * + * Supplied IGVM file replaces the firmware for one reset. Resetting + * again will switch back to the original firmware. Updating the + * firmware again is NOT possible. + * + */ + +/* status code */ +enum VMLaunchUpdateStatus { + VM_LAUNCHUPDATE_SUCCESS =3D 0, + VM_LAUNCHUPDATE_LOAD_FAIL =3D 1, + VM_LAUNCHUPDATE_NOT_IGVM_INIT =3D 2, +}; + +typedef struct QEMU_PACKED { + /* api version */ + uint16_t version; + + /* + * The guest can read this in order to determine if loading new IGVM + * succeeded. + */ + uint16_t status; + + uint32_t _padding; + + /* VMM capabilities, read-only. */ + uint64_t capabilities; + /* control bits, see VMFWUPDATE_CTL_* */ + uint64_t control; + + /* + * address and size of the IGVM image. Will be cleared when + * the write completes successfully and IGVM file is correctly parsed. + */ + uint64_t fw_image_addr; + uint64_t fw_image_size; + + /* + * address + size of opaque blob. The guest can use this to pass on + * information, for example which memory region the linux kernel has b= een + * loaded to. writable, will be kept intact on firmware update. + */ + uint64_t opaque_addr; + uint64_t opaque_size; + +} VMLaunchUpdate; + +#endif --=20 2.55.0 From nobody Fri Aug 21 21:27:09 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1787328796; cv=none; d=zohomail.com; s=zohoarc; b=YW4hxVmRnqdq1jdtla0MdWwwOrILiR61xhFUu9doqU2nI2gVYvdOqm1tBbelU0BoA6A8TQ9XnzUBJt0bdIpTrz+578OpshNe5pyZcHXxAdQwlxPREMXGJWbqNo3UJV3FhpVtyQUoJu+/+LySNQE2TAICmKrzAxY/aGAmMVss6JE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787328796; 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=X5UjZVGY+Rx/JaSswrp4uAc+3mwSdzF/MroO9dyBRxI=; b=f7tl0TB2xULGFz6Q6+9zsduggmdtU8gw3lUTssG4fEZ1mHYW6oHipzvGMYiIwaWE/lhAf/oHXEOBojW7JgvWQqyjp70cALPrj2b2/D/Q4sP5FUDH/6fYv4kAhIQIHLr6H3cDTf/83THKho0m1wQI0bEoys/LnK1qtNjvNhWgEGA= 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=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787328796136185.59793199603564; Fri, 21 Aug 2026 09:13:16 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wxRpy-0006Y2-Dy; Fri, 21 Aug 2026 12:11:22 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRpw-0006Wz-Pn for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:20 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRpt-0001Z7-Fd for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:20 -0400 Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-589-uFGTdhQdPbKwvE2LN21Kew-1; Fri, 21 Aug 2026 12:11:12 -0400 Received: from mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.95]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id CF6531953994; Fri, 21 Aug 2026 16:11:10 +0000 (UTC) Received: from sirius.home.kraxel.org (unknown [10.44.48.30]) by mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 4CF4B7DD; Fri, 21 Aug 2026 16:11:10 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id E07CB1801036; Fri, 21 Aug 2026 18:11:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787328676; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=X5UjZVGY+Rx/JaSswrp4uAc+3mwSdzF/MroO9dyBRxI=; b=KgqolbFDCjMV9tHzk+KrKmri7+91cK5GdY9Z5dg1lNwXJjAeRhHVgEb9hEItYTsJfdoRqH K0ZWOLdSThm94DGUMNr5DQCOiPXT8Rx388rnStdU+4vOU3tjQpY6csb7rbZVuIt+TRK4IW ME0vthqJqL7YyrSBC1dSNkhn65dsmBQ= X-MC-Unique: uFGTdhQdPbKwvE2LN21Kew-1 X-Mimecast-MFC-AGG-ID: uFGTdhQdPbKwvE2LN21Kew_1787328670 From: Gerd Hoffmann To: qemu-devel@nongnu.org Cc: Ani Sinha , Cornelia Huck , Peter Maydell , Zhao Liu , Peter Xu , qemu-arm@nongnu.org, Pierrick Bouvier , Gerd Hoffman , "Michael S. Tsirkin" , Stefano Garzarella , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Laurent Vivier , Fabiano Rosas , Paolo Bonzini , Alex Graf Subject: [PULL 08/12] hw/misc/vmlaunchupdate: Introduce hypervisor fw-cfg interface support Date: Fri, 21 Aug 2026 18:10:56 +0200 Message-ID: <20260821161103.3489298-9-kraxel@redhat.com> In-Reply-To: <20260821161103.3489298-1-kraxel@redhat.com> References: <20260821161103.3489298-1-kraxel@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.6 on 10.30.177.95 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=lists1p.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 9 X-Spam_score: 0.9 X-Spam_bar: / X-Spam_report: (0.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.341, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=0.001, RCVD_IN_SBL_CSS=3.335, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action 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 @redhat.com) X-ZM-MESSAGEID: 1787328798310158500 Content-Type: text/plain; charset="utf-8" From: Ani Sinha VM launch update is a mechanism where the virtual machines can use IGVM file bundle to boot into a trusted execution environment without having to depend on a untrusted party to provide the IGVM bundle or firmware image. This is particularly useful for confidential virtual machines that are deployed in the cloud where the tenant and the cloud provider are two different entities. In this scenario, virtual machines can bring their own trusted IGVM file containing a trusted firmware image bundled as a part of their filesystem and then use this hypervisor interface to update to a trusted and deterministic boot state. This also allows the guests to have a consistent measurements on the firmwa= re image. Currently, this mechanism only works if the VM was started with IGVM in the first place. This change introduces support for the fw-cfg based hypervisor interface and the corresponding device. The interface is made generic enough so that guests are free to use their own ABI to pass required information between initial and trusted execution contexts (where they are running their own trusted boot state) without the hypervisor getting involved in between. Currently, this device is only supported for x86_64 machines. Presence of IGVM host libraries is also required for parsing IGVM files. Hence, the dev= ice cannot be initialized for other machine types or hosts where IGVM support is not present. Trying to initialize it for arm for example will lead to fa= ilure: $ ./qemu-system-arm -device vm-launch-update -machine virt qemu-system-arm: -device vm-launch-update: This machine does not support vm= -launch-update device A document detailing the specification is added in a subsequent patch. Plea= se see docs/specs/vmlaunchupdate.rst. Functional and qtests are added in a subsequent patch. CC: Alex Graf CC: Gerd Hoffman Reviewed-by: Gerd Hoffmann Reviewed-by: Alexander Graf Signed-off-by: Ani Sinha Message-ID: <20260817142010.80693-8-anisinha@redhat.com> Signed-off-by: Gerd Hoffmann --- include/hw/misc/vmlaunchupdate.h | 38 ++++ hw/misc/vmlaunchupdate.c | 333 +++++++++++++++++++++++++++++++ hw/misc/meson.build | 3 + hw/misc/trace-events | 6 + 4 files changed, 380 insertions(+) create mode 100644 include/hw/misc/vmlaunchupdate.h create mode 100644 hw/misc/vmlaunchupdate.c diff --git a/include/hw/misc/vmlaunchupdate.h b/include/hw/misc/vmlaunchupd= ate.h new file mode 100644 index 000000000000..02f96cebdc17 --- /dev/null +++ b/include/hw/misc/vmlaunchupdate.h @@ -0,0 +1,38 @@ +/* + * Guest driven VM launch state update device via IGVM. + * For details and specification, please look at docs/specs/vmlaunchupdate= .rst. + * + * Copyright (C) 2026 Red Hat, Inc. + * + * Authors: Ani Sinha + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + */ +#ifndef VMLAUNCHUPDATE_H +#define VMLAUNCHUPDATE_H + +#include "hw/core/qdev.h" +#include "qom/object.h" +#include "qemu/units.h" +#include "system/igvm-cfg.h" +#include "standard-headers/misc/vmlaunchupdate.h" + +#define TYPE_VMLAUNCHUPDATE "vm-launch-update" + +typedef struct VMLaunchUpdateState { + DeviceState parent_obj; + VMLaunchUpdate launch_update; + bool disabled; + bool host_igvm_on_reset; + ResettableState reset_state; +} VMLaunchUpdateState; + + +typedef struct VMLaunchUpdateStateClass { + ObjectClass parent_class; +} VMLaunchUpdateStateClass; + +OBJECT_DECLARE_SIMPLE_TYPE(VMLaunchUpdateState, VMLAUNCHUPDATE); + +#endif diff --git a/hw/misc/vmlaunchupdate.c b/hw/misc/vmlaunchupdate.c new file mode 100644 index 000000000000..afa2d278aefc --- /dev/null +++ b/hw/misc/vmlaunchupdate.c @@ -0,0 +1,333 @@ +/* + * Guest driven VM launch component update (using IGVM) device + * For details and specification, please look at docs/specs/vmlaunchupdate= .rst. + * + * Copyright (C) 2026 Red Hat, Inc. + * + * Authors: Ani Sinha + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/module.h" +#include "system/physmem.h" +#include "system/reset.h" +#include "qemu/target-info-qapi.h" +#include "hw/nvram/fw_cfg.h" +#include "hw/core/qdev-properties.h" +#include "hw/i386/pc.h" +#include "exec/cpu-common.h" +#include "hw/misc/vmlaunchupdate.h" +#include "system/igvm.h" +#include "system/igvm-internal.h" +#include "qemu/error-report.h" +#include "trace.h" + +/* returns NULL unless there is exactly one device */ +static VMLaunchUpdateState *vm_launchupdate_find(void) +{ + Object *o =3D object_resolve_path_type("", TYPE_VMLAUNCHUPDATE, NULL); + + return o ? VMLAUNCHUPDATE(o) : NULL; +} + +static bool vmlaunchupdate_supported(void) +{ + return target_arch() =3D=3D SYS_EMU_TARGET_X86_64; +} + +static void init_vm_launch_update(VMLaunchUpdateState *s) +{ + s->launch_update.capabilities =3D VM_LAUNCHUPDATE_FORMAT_IGVM; + s->launch_update.control =3D 0; + + if (s->disabled) { + s->launch_update.control |=3D VM_LAUNCHUPDATE_CTL_DISABLE; + } + + s->launch_update.version =3D VM_LAUNCHUPDATE_VERSION; + return; +} + +static void clear_init_vm_launch_update(VMLaunchUpdateState *s) +{ + memset(&s->launch_update, 0, sizeof(s->launch_update)); + init_vm_launch_update(s); +} + +static bool no_igvmcfg(X86MachineState *x86m) +{ + IgvmCfg *igvmc; + + if (!x86m) { + return true; + } + + igvmc =3D x86m->igvm; + + if (!igvmc) { + /* The VM was not started with an IGVM, bail */ + info_report("guest was not initially started with IGVM, " + "not changing launch state."); + return true; + } + return false; +} + +static int process_x86_igvm(VMLaunchUpdateState *s, + uint64_t fw_image_addr, uint64_t fw_image_size) +{ + X86MachineState *x86machine =3D X86_MACHINE(qdev_get_machine()); + IgvmCfg *igvmc =3D x86machine->igvm; + IgvmHandle igvm; + void *image_addr_ptr; + hwaddr len; + + if (no_igvmcfg(x86machine)) { + return -2; + } + + if (!fw_image_addr || !fw_image_size) { + return -1; + } + + len =3D (hwaddr) fw_image_size; + image_addr_ptr =3D physical_memory_map((hwaddr) fw_image_addr, + (hwaddr *) &len, 0); + + if (!image_addr_ptr || (len < fw_image_size)) { + warn_report("vmlaunchupdate: Invalid guest addresses."); + goto err; + } + + igvm =3D igvm_new_from_binary(image_addr_ptr, fw_image_size); + if (igvm < 0) { + warn_report("vmlaunchupdate: Unable to parse IGVM file %" + PRIx64 ": %" PRIx64, fw_image_addr, fw_image_size); + goto err; + } + + /* free previous file context */ + if (igvmc->file >=3D 0) { + igvm_free(igvmc->file); + } + /* set new context */ + igvmc->file =3D igvm; + + physical_memory_unmap(image_addr_ptr, len, 0, 0); + info_report("vmlaunchupdate: new IGVM context set."); + + return 0; + err: + if (image_addr_ptr) { + physical_memory_unmap(image_addr_ptr, len, 0, 0); + } + return -1; +} + +static void restore_host_x86_igvm(void) +{ + X86MachineState *x86machine =3D X86_MACHINE(qdev_get_machine()); + IgvmCfg *igvmc =3D x86machine->igvm; + Error *errp =3D NULL; + + if (no_igvmcfg(x86machine)) { + return; + } + + /* free previous file context */ + if (igvmc->file >=3D 0) { + igvm_free(igvmc->file); + } + + info_report("restoring original host IGVM: %s", igvmc->filename); + igvmc->file =3D qigvm_file_init(igvmc->filename, &errp); + assert(!errp); + + info_report("vmlaunchupdate: host IGVM context set."); + + trace_restore_host_x86_igvm(); + + return; +} + +static bool fw_address_cleared(VMLaunchUpdateState *s) +{ + return !s->launch_update.fw_image_addr && + !s->launch_update.fw_image_size; +} + +static void launch_update_write(void *dev, off_t offset, size_t len) +{ + VMLaunchUpdateState *s =3D VMLAUNCHUPDATE(dev); + uint64_t addr; + uint64_t size; + int rc; + + s->launch_update.status =3D VM_LAUNCHUPDATE_SUCCESS; + + if (s->disabled) { + goto end; + } + + if (s->launch_update.control & VM_LAUNCHUPDATE_CTL_DISABLE) { + s->disabled =3D true; + goto end; + } + + if (fw_address_cleared(s) && + (s->launch_update.control & VM_LAUNCHUPDATE_CTL_HOST_IGVM)) { + /* restore host IGVM on immediate next reset */ + s->host_igvm_on_reset =3D true; + goto end; + } + + if (!(s->launch_update.control & VM_LAUNCHUPDATE_FORMAT_IGVM) && + !fw_address_cleared(s)) { + /* at least one address provided but the format is not IGVM */ + s->launch_update.status =3D VM_LAUNCHUPDATE_LOAD_FAIL; + goto end; + } + + /* process guest provided IGVM image */ + if (s->launch_update.control & VM_LAUNCHUPDATE_FORMAT_IGVM) { + if (target_arch() =3D=3D SYS_EMU_TARGET_X86_64) { + addr =3D le64_to_cpu(s->launch_update.fw_image_addr); + size =3D le64_to_cpu(s->launch_update.fw_image_size); + rc =3D process_x86_igvm(s, addr, size); + if (rc < 0) { + switch (rc) { + case -2: + s->launch_update.status =3D VM_LAUNCHUPDATE_NOT_IGVM_I= NIT; + break; + default: + s->launch_update.status =3D VM_LAUNCHUPDATE_LOAD_FAIL; + } + goto end; + } + } + /* process other machines here when support is added */ + } + + /* clear the addresses */ + s->launch_update.fw_image_addr =3D 0x0; + s->launch_update.fw_image_size =3D 0x0; + + end: + trace_launch_update_write(); + return; +} + +static void launch_update_select(void *dev) +{ + VMLaunchUpdateState *s =3D VMLAUNCHUPDATE(dev); + init_vm_launch_update(s); +} + +static void vmlaunch_reset_enter(Object *obj, ResetType type) +{ + VMLaunchUpdateState *s =3D VMLAUNCHUPDATE(obj); + + if (target_arch() !=3D SYS_EMU_TARGET_X86_64) { + return; + } + + if (s->host_igvm_on_reset) { + restore_host_x86_igvm(); + s->host_igvm_on_reset =3D false; + /* restoring host igvm enables the interface again */ + s->disabled =3D false; + /* clear the host IGVM ctrl bit */ + s->launch_update.control &=3D ~VM_LAUNCHUPDATE_CTL_HOST_IGVM; + } + + if ((s->launch_update.control & VM_LAUNCHUPDATE_CTL_HOST_IGVM) && + (s->launch_update.status =3D=3D VM_LAUNCHUPDATE_SUCCESS)) { + info_report("vmlaunchupdate: next reset will use host igvm"); + s->host_igvm_on_reset =3D true; + } + + trace_vmlaunch_reset_enter(); +} + +static ResettableState *vmlaunch_reset_state(Object *obj) +{ + VMLaunchUpdateState *s =3D VMLAUNCHUPDATE(obj); + + return &s->reset_state; +} + +static void vm_launchupdate_realize(DeviceState *dev, Error **errp) +{ + VMLaunchUpdateState *s =3D VMLAUNCHUPDATE(dev); + FWCfgState *fw_cfg =3D fw_cfg_find(); + + /* multiple devices are not supported */ + if (!vm_launchupdate_find()) { + error_setg(errp, "at most one %s device is permitted", + TYPE_VMLAUNCHUPDATE); + return; + } + + /* if current machine is not supported, do not initialize */ + if (!vmlaunchupdate_supported()) { + error_setg(errp, + "This machine does not support vm-launch-update device"= ); + return; + } + + /* fw_cfg with DMA support is necessary to support this device */ + if (!fw_cfg || !fw_cfg_dma_enabled(fw_cfg)) { + error_setg(errp, "%s device requires fw_cfg", + TYPE_VMLAUNCHUPDATE); + return; + } + + fw_cfg_add_file_callback(fw_cfg, FILE_VMLAUNCHUPDATE, + launch_update_select, launch_update_write, s, + &s->launch_update, + sizeof(s->launch_update), + false); + + clear_init_vm_launch_update(s); + /* + * This device requires to register a global reset because it is + * not plugged to a bus (which, as its QOM parent, would reset it). + */ + qemu_register_resettable(OBJECT(s)); +} + +static void vm_launchupdate_finalize(Object *obj) +{ + qemu_unregister_resettable(obj); + trace_vm_launchupdate_finalize(); +} + +static void vmlaunchupdate_device_class_init(ObjectClass *klass, + const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + + /* we are not interested in migration - so no need to populate dc->vms= d */ + dc->desc =3D "VM launch state update device"; + dc->realize =3D vm_launchupdate_realize; + dc->hotpluggable =3D false; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + rc->phases.enter =3D vmlaunch_reset_enter; + rc->get_state =3D vmlaunch_reset_state; +} + +static const TypeInfo vmlaunchupdate_device_types[] =3D { + { + .name =3D TYPE_VMLAUNCHUPDATE, + .parent =3D TYPE_DEVICE, + .instance_size =3D sizeof(VMLaunchUpdateState), + .class_init =3D vmlaunchupdate_device_class_init, + .instance_finalize =3D vm_launchupdate_finalize, + }, +}; + +DEFINE_TYPES(vmlaunchupdate_device_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build index e86d9ad6b39b..858ca845a2d3 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -164,6 +164,9 @@ specific_ss.add(when: 'CONFIG_MIPS_ITU', if_true: files= ('mips_itu.c')) =20 specific_ss.add(when: 'CONFIG_RISCV_MIPS_CMGCR', if_true: files('riscv_cmg= cr.c')) specific_ss.add(when: 'CONFIG_RISCV_MIPS_CPC', if_true: files('riscv_cpc.c= ')) +if igvm.found() + specific_ss.add(when: 'CONFIG_FW_CFG_DMA', if_true: files('vmlaunchupda= te.c')) +endif =20 system_ss.add(when: 'CONFIG_SBSA_REF', if_true: files('sbsa_ec.c')) =20 diff --git a/hw/misc/trace-events b/hw/misc/trace-events index c9a868b3efb9..2d6d2238c57b 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -442,3 +442,9 @@ iommu_testdev_dma_read(uint64_t gva, uint32_t len) "gva= =3D0x%" PRIx64 " len=3D%u" iommu_testdev_dma_verify(uint32_t expected, uint32_t actual) "expected=3D0= x%x actual=3D0x%x" iommu_testdev_dma_result(uint32_t result) "DMA completed result=3D0x%x" iommu_testdev_dma_armed(bool armed) "armed=3D%d" + +# vmlaunchupdate.c +launch_update_write(void) "" +vmlaunch_reset_enter(void) "" +vm_launchupdate_finalize(void) "" +restore_host_x86_igvm(void) "" --=20 2.55.0 From nobody Fri Aug 21 21:27:09 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1787328802; cv=none; d=zohomail.com; s=zohoarc; b=eAcz56B/EUpzbKIg8hsaUrkXWM3SRGmf+pHmeLG/0aKHwkJvQ2rcdO08NsepUJIqn87ylCrRY1+4YgKFxIHkHYOn1l+9VDPM1zCxa6ezF24snoN9E+pHhG2pL+ezruWlA+gWc/gjyW4dWwrXMVBx3KBhFm+7qUQkiX5kJJ1ZYkY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787328802; 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=bfbONaxa0yS3q1QeVM9oaKCkGpU1oU9TEtuSmszrRSc=; b=iwZH7S+oQ1P0yQ0ClMkKlFoUgsdM4Hdcssd7oWCWlJhXDUEY4ahWxsMPSX7YwsaUVnw3MVcQ0+20XkTS1o5q2YYU103nllWGzumXxjiVR1CRYENu0ESe9VgHdJeuDZdKN9jpOZRiw6rbeftonPcZYO4tzb/MHrljkfKCqUHqnmU= 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=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787328802785387.6632812768479; Fri, 21 Aug 2026 09:13:22 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wxRq3-0006ao-5V; Fri, 21 Aug 2026 12:11:27 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRpu-0006VZ-Qz for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:18 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRps-0001Yc-D3 for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:18 -0400 Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-589-oJlJHhrwOp-T31fhH3bnTQ-1; Fri, 21 Aug 2026 12:11:12 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id DD68819539A7; Fri, 21 Aug 2026 16:11:10 +0000 (UTC) Received: from sirius.home.kraxel.org (unknown [10.44.48.30]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 9616A1800346; Fri, 21 Aug 2026 16:11:10 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id F3C2F180103A; Fri, 21 Aug 2026 18:11:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787328675; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=bfbONaxa0yS3q1QeVM9oaKCkGpU1oU9TEtuSmszrRSc=; b=YyyPCMHkyQUQ1v7mPE+eqzpxgzeASXVozPAUH0Isnf0BgnBbu6Os2Ki2ZwidsN8tpvV2KH imgNpvu0RCKXBzJGrK1WJppWXF8CGqnvjWOasGFy6kZ5YnpJBFOBJk4prb0qBZV1ESR8Rh i2byAA5mhLnZhfQpSucUB5mwp6s693E= X-MC-Unique: oJlJHhrwOp-T31fhH3bnTQ-1 X-Mimecast-MFC-AGG-ID: oJlJHhrwOp-T31fhH3bnTQ_1787328671 From: Gerd Hoffmann To: qemu-devel@nongnu.org Cc: Ani Sinha , Cornelia Huck , Peter Maydell , Zhao Liu , Peter Xu , qemu-arm@nongnu.org, Pierrick Bouvier , Gerd Hoffman , "Michael S. Tsirkin" , Stefano Garzarella , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Laurent Vivier , Fabiano Rosas , Paolo Bonzini , Alex Graf Subject: [PULL 09/12] docs/spec: Add a specification document for vm-launch-update device Date: Fri, 21 Aug 2026 18:10:57 +0200 Message-ID: <20260821161103.3489298-10-kraxel@redhat.com> In-Reply-To: <20260821161103.3489298-1-kraxel@redhat.com> References: <20260821161103.3489298-1-kraxel@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 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=lists1p.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 9 X-Spam_score: 0.9 X-Spam_bar: / X-Spam_report: (0.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.341, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=0.001, RCVD_IN_SBL_CSS=3.335, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action 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 @redhat.com) X-ZM-MESSAGEID: 1787328804371158500 Content-Type: text/plain; charset="utf-8" From: Ani Sinha This change adds a specification document and expanation for the vm-launch-update device. CC: Alex Graf CC: Gerd Hoffman Reviewed-by: Alexander Graf Signed-off-by: Ani Sinha Message-ID: <20260817142010.80693-9-anisinha@redhat.com> Signed-off-by: Gerd Hoffmann --- docs/specs/index.rst | 1 + docs/specs/vmlaunchupdate.rst | 198 ++++++++++++++++++++++++++++++++++ 2 files changed, 199 insertions(+) create mode 100644 docs/specs/vmlaunchupdate.rst diff --git a/docs/specs/index.rst b/docs/specs/index.rst index b7909a108ab9..3cdf242661b4 100644 --- a/docs/specs/index.rst +++ b/docs/specs/index.rst @@ -34,6 +34,7 @@ guest hardware that is specific to QEMU. virt-ctlr vmcoreinfo vmgenid + vmlaunchupdate rapl-msr rocker riscv-iommu diff --git a/docs/specs/vmlaunchupdate.rst b/docs/specs/vmlaunchupdate.rst new file mode 100644 index 000000000000..2f1e95afbffa --- /dev/null +++ b/docs/specs/vmlaunchupdate.rst @@ -0,0 +1,198 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +VMLAUNCHUPDATE Interface Specification +###################################### + +Introduction +************ + +``VmLaunchUpdate`` is an extension to ``fw-cfg`` that allows guests to rep= lace +boot state in their virtual machine using IGVM file container. Through a c= ombination +of this ``fw-cfg`` hypervisor interface, an IGVM file containing specific = directives +and with hypervisor stack knowledge, guests can deterministically replace = the launch +state for guests. This is useful for environments like SEV-SNP where the +launch payload becomes the launch digest. Guests can use vm-launch-update = device to +provide a measured, full guest payload (BIOS image, kernel, initramfs, ker= nel +command line) to the virtual machine which enables them to easily reason a= bout +integrity of the resulting system. +It is also to be noted that this mechanism currently works only when the g= uest was +already started with an IGVM file defining its initial launch state. Subse= quent +guest resets will use the launch state as defined in the guest provided IG= VM file, +not the file with which the guest was initially started. If the guest was = not started +with IGVM, writing a new bundle through the ``fw-cfg`` interface has no ef= fect. + +For more information, please see the `KVM Forum 2024 presentation `__ +about this work. + + +.. _KVMFORUM: https://www.youtube.com/watch?v=3DVCMBxU6tAto + +Base Requirements +***************** + +#. **fw-cfg**: + The target system must provide a ``fw-cfg`` interface. For x86 based + environments, this ``fw-cfg`` interface must be accessible through PI= O ports + 0x510 and 0x511. The ``fw-cfg`` interface does not need to be announc= ed as part + of system device tables such as DSDT. The ``fw-cfg`` interface must s= upport the + DMA interface. It may only support the DMA interface for write operat= ions. + +#. **IGVM support**: + The hypervisor must provide support for parsing and executing the IGV= M file bundle. + +#. **Confidential guests**: + For confidential guests, the hypervisor must support guest reset. Oth= erwise, the new + boot state provided through IGVM will not be applied. + +The Fw-cfg File +*************** + +Guests drive vmlaunchupdate through special ``fw-cfg`` files that control = its flow +followed by a standard system reset operation. When the ``vm-launch-update= `` device +is available, it provides the following ``fw-cfg`` file: + +* ``etc/vmlaunchupdate`` - It exposes a structure of the following type, a= ll in + little-endian format: + +.. code-block:: c + :linenos: + + typedef struct { + uint16_t version; + uint16_t status; + + uint32_t _padding; + + uint64_t capabilities; + uint64_t control; + + uint64_t fw_image_addr; + uint64_t fw_image_size; + + uint64_t opaque_addr; + uint64_t opaque_size; + + } VMLaunchUpdate; + + +Currently, the ``version`` number (line 2 above) is initialized to the val= ue ``1``. +Only IGVM files are supported at present. The ``capabilities`` (line 7) an= d ``control`` (line 8) both support +the following single value: + +* ``VM_LAUNCHUPDATE_FORMAT_IGVM`` + + This value is used by the hypervisor to indicate that only IGVM containe= r files are supported. + This is set as a part of ``capabilities`` parameter (line 7) in the abo= ve structure. This same value + is passed by the guest to the hypervisor in the ``control`` parameter (l= ine 8) in the above structure + to indicate that the guest passed IGVM file in memory to the hypervisor.= The starting guest physical + address of the IGVM file in memory is specified in ``fw_image_addr`` and= it's length is specified in + ``fw_image_size`` by the guest. If any other value is passed by the gues= t in the ``control`` parameter, + the write is ignored by the hypervisor. + +Following ``control`` parameters are supported: + +* ``VM_LAUNCHUPDATE_CTL_DISABLE`` + + This value is set in the ``control`` parameter by the guest in order to = disable this ``fw-cfg`` + hypervisor interface from further updating the guest launch state with a= new IGVM file. + +* ``VM_LAUNCHUPDATE_CTL_HOST_IGVM`` + + This value is set in the ``control`` parameter by the guest in order to = send request to the + hypervisor to initialize the guest using the original host provided IGVM= file. + It is useful if the guest wanted to update the UKIs present in the ESP a= nd upon + reset, use one of the updated UKIs present there. If the guest passed ad= dresses in memory + where its own IGVM file is loaded (see below) while also setting this co= ntrol value, the next + reset will load the guest provided IGVM file and a subsequent second res= et will restore the original + host IGVM. If the guest did not provide any addresses of its own IGVM (t= he address values are + cleared) while setting this control parameter, the immediate next guest = reset will load the + original host provided IGVM file. + + The combination of the above two ctl interfaces work as + follows: + + A) ``CTL_HOST_IGVM`` =3D off ``CTL_DISABLE`` =3D off + + Supplied IGVM file replaces the firmware permanently. Updating the + firmware again is possible. + + B) ``CTL_HOST_IGVM`` =3D off ``CTL_DISABLE`` =3D on + + Supplied IGVM file replaces the firmware permanently. Updating the + firmware again is not possible. + + C) ``CTL_HOST_IGVM`` =3D on ``CTL_DISABLE`` =3D off + + Supplied IGVM file replaces the firmware for one reset. Resetting + again will switch back to the original firmware. Updating the + firmware again is possible. + + D) ``CTL_HOST_IGVM`` =3D on ``CTL_DISABLE`` =3D on + + Supplied IGVM file replaces the firmware for one reset. Resetting + again will switch back to the original firmware. Updating the + firmware again is NOT possible. + +``fw_image_addr`` (line 10) is the base guest physical address of the gues= t memory where the IGVM file of size +``fw_image_size`` (line 11) is loaded. ``opaque_addr`` (line 13) and ``opa= que_size`` (line 14) are used by +the guest for passing data across resets. The contents of this guest memor= y are preserved across the +reset. For confidential guests, this memory region must come from guest sh= ared unencrypted memory. + +``status`` (line 3) is written by the hypervisor and it indicates the resu= lt of the IGVM loading operation. +A success indicates status code 0. Otherwise a non-zero status code indica= tes failure. The nature of the +failure is indicated by the value of the code. + +Triggering the Launch State Update using IGVM +********************************************* + +To initiate the launch update process, the guest issues a standard system = reset +operation through any of the means implemented by the machine model. + +On a write to the ``etc/vmlaunchupdate`` interface, the hypervisor evaluat= es whether this +hypervisor interface is disabled. If it is, it ignores any writes to this = ``fw-cfg`` file +by the guest. No updates to initial launch state is performed. + +If the hypervisor interface is enabled, upon write to the ``etc/vmlaunchup= date`` interface, +the hypervisor parses the IGVM file bundle passed to it in memory, with st= arting guest physical +address at ``fw_image_addr`` and length ``fw_image_size``. If parsing is s= uccessful, it creates +a context handle to the IGVM file. If parsing and context loading is succe= ssful and there are no +errors, ``fw_image_addr`` and ``fw_image_size`` are cleared. The guest can= check this in order +to determine if the IGVM was successfully parsed and the new context was l= oaded. If not, the +guest can throw error and abort rebooting to new IGVM boot state. Alternat= ively, the guest can +also check the ``status`` code from the ``fw-cfg`` file. A status code of = 0 indicates success +of the operation. Non-zero status code indicates failure. Exact nature of = the failure is +indicated by the value of the code. Currently, only two error values are s= upported: + +* ``VM_LAUNCHUPDATE_LOAD_FAIL`` - defined as value 1 and is set when loadi= ng of the IGVM file failed. +* ``VM_LAUNCHUPDATE_NOT_IGVM_INIT`` - defined as value 2 and is set when t= he guest was not started with + IGVM file. + +Upon guest reset, the hypervisor executes the IGVM bundle using +the context handle, setting the initial launch state of the guest accordin= gly. +If an invalid IGVM file is passed, parsing the file fails and the hypervis= or ignores it +when ``fw-cfg`` files are written. In this case, the initial launch state +is not modified. If invalid addresses are passed, the hypervisor ignores t= hem as well and no +new launch state is set. + +The launch state update mechanism works both for confidential and non-conf= idential +guests. In confidential guests, as a part of the reset operation, all exis= ting +guest shared memory (shared with the hypervisor) as well as the guest memo= ry region +starting with ``opaque_addr`` and length ``opaque_size`` are preserved. +The reset causes recreation of the VM context which triggers a fresh +measurement of the replaced BIOS region and reset CPU state. + +For non-confidential guests, there is no concept of guest private memory a= nd all the existing +guest memory is preserved (this is the default behaviour today - QEMU does= not reset/clear +guest memory upon reset). + +In both confidential and non-confidential cases, CPU and device state are = reset to +the reset states specified in IGVM. In confidential environments, the guest +always resumes operation in the highest privileged mode available to it (V= MPL0 in SEV-SNP). + +Closing Remarks +*************** +The exact content of the memory region specified by starting address ``opa= que_addr`` +and length ``opaque_size`` is guest specific and is hypervisor agnostic. T= he hypervisor does +not care about the contents of this memory region. Therefore, it is not in= cluded in this +specification. As of writing this document, TDX guests on QEMU does not su= pport IGVM. +Therefore, this mechanism cannot be used to change launch state of TDX gue= sts. --=20 2.55.0 From nobody Fri Aug 21 21:27:09 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1787328709; cv=none; d=zohomail.com; s=zohoarc; b=dUqiYLBeY4ruEH+Kp33SgduhHXsQFDI2AA3v46zYLeDIaQRoRZ7RgGLOvP//BzAkz98wr52iZtbnS8fF5bsmUTylwIJAAFyOKC0psIpLwChPpXBiealk0o8q3t5bStEWDw1/N3aNR4gXpC7Tj1ct+2VXDcGuL9Elham5lbZUdxo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787328709; 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=auQ6ahux3rX9SNpR09XMp2vpl6QM9tcvF0R6HyBKfS4=; b=DWkfTBfChqB6JFLlv601Cz60UcOkzmtcce3WeYZRRZIGAFoHqTpjgVhZQXNnfSx+ZICqFdzIER7d2k9x69fAK2Xuygn+UFEN9IL7Wqyec00tPw+jQQOLpux3yn4TyLpJBm2qdFzE1/peldVK9ONHQQGgJuUQjjuUO75D01Zcc/Q= 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=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787328709053706.755433160965; Fri, 21 Aug 2026 09:11:49 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wxRq5-0006cQ-A0; Fri, 21 Aug 2026 12:11:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRq2-0006ak-IY for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:26 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRpv-0001a6-IY for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:26 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-621-MCMjDmmUM222tlHUvQDhZw-1; Fri, 21 Aug 2026 12:11:13 -0400 Received: from mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.95]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 17F711802158; Fri, 21 Aug 2026 16:11:12 +0000 (UTC) Received: from sirius.home.kraxel.org (unknown [10.44.48.30]) by mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 4ED9C426; Fri, 21 Aug 2026 16:11:11 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 1714C1801081; Fri, 21 Aug 2026 18:11:04 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787328678; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=auQ6ahux3rX9SNpR09XMp2vpl6QM9tcvF0R6HyBKfS4=; b=cLfRdoCA0++ZPcyYOzVWxxO5r6LkWetQ9xM89MshreO+I/7O+0BEshm8wi89b2RM2XSQTQ U0UjFYEhx4QGrjLKi1QTrrCc0+55q0X/UXwc3nzYHcEru+NJVXHEIJgGvBTebL00XTM3hV fUG8QdDDGtNeIoc5akZ/N8nUy+loGV0= X-MC-Unique: MCMjDmmUM222tlHUvQDhZw-1 X-Mimecast-MFC-AGG-ID: MCMjDmmUM222tlHUvQDhZw_1787328672 From: Gerd Hoffmann To: qemu-devel@nongnu.org Cc: Ani Sinha , Cornelia Huck , Peter Maydell , Zhao Liu , Peter Xu , qemu-arm@nongnu.org, Pierrick Bouvier , Gerd Hoffman , "Michael S. Tsirkin" , Stefano Garzarella , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Laurent Vivier , Fabiano Rosas , Paolo Bonzini , Alex Graf Subject: [PULL 10/12] tests/qtest: Add small igvm files for testing purpose Date: Fri, 21 Aug 2026 18:10:58 +0200 Message-ID: <20260821161103.3489298-11-kraxel@redhat.com> In-Reply-To: <20260821161103.3489298-1-kraxel@redhat.com> References: <20260821161103.3489298-1-kraxel@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.6 on 10.30.177.95 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=lists1p.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -23 X-Spam_score: -2.4 X-Spam_bar: -- X-Spam_report: (-2.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.341, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action 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 @redhat.com) X-ZM-MESSAGEID: 1787328711900158500 Content-Type: text/plain; charset="utf-8" From: Ani Sinha Needed by launchupdate-test.c. README file is added with explanation on how to build these IGVM files. CC: Alex Graf CC: Gerd Hoffman Reviewed-by: Alexander Graf Signed-off-by: Ani Sinha Message-ID: <20260817142010.80693-10-anisinha@redhat.com> Signed-off-by: Gerd Hoffmann --- tests/data/igvm/README | 45 ++++++++++++++++++++++++++++++++++ tests/data/igvm/hello.igvm | Bin 0 -> 137112 bytes tests/data/igvm/qemuinit.igvm | Bin 0 -> 137112 bytes 3 files changed, 45 insertions(+) create mode 100644 tests/data/igvm/README create mode 100644 tests/data/igvm/hello.igvm create mode 100644 tests/data/igvm/qemuinit.igvm diff --git a/tests/data/igvm/README b/tests/data/igvm/README new file mode 100644 index 000000000000..d4d26478eeb9 --- /dev/null +++ b/tests/data/igvm/README @@ -0,0 +1,45 @@ + +=3D=3D=3D This is the readme file for all IGVM file bundles provided =3D= =3D=3D +=3D=3D=3D All IGVM files are covered by GPL v2 or later =3D=3D=3D +SPDX-License-Identifier: GPL-2.0-or-later + +Small IGVM file bundles required for tesing vm-launch-update device +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +This directory contains IGVM files required for launchupdate-test.c. +These IGVM bundles can be built from the following repository: + +https://gitlab.com/anisinha/virt-firmware-rs + +Just type "make" in the top of the repository. The built IGVM files +can be found in the target/x86_64-unknown-none/debug directory. + +$ ls -l ./target/x86_64-unknown-none/debug/*.igvm +-rw-r--r--. 1 anisinha anisinha 153624 Jun 8 10:05 ./target/x86_64-unknow= n-none/debug/hello.igvm +-rw-r--r--. 1 anisinha anisinha 157848 Jun 8 10:05 ./target/x86_64-unknow= n-none/debug/igvmtest.igvm +-rw-r--r--. 1 anisinha anisinha 987384 Jun 8 10:05 ./target/x86_64-unknow= n-none/debug/mefisto.igvm +-rw-r--r--. 1 anisinha anisinha 368312 Jun 8 10:05 ./target/x86_64-unknow= n-none/debug/qemuinit.igvm +-rw-r--r--. 1 anisinha anisinha 223944 Jun 8 10:05 ./target/x86_64-unknow= n-none/debug/snptest.igvm + +The IGVM bundles for sev-snp testing are also kept in a seperate directory= /snp_igvm_bundles in the +above repository for use without requiring to build from source: + +$ virtfirmware-rs/snp_igvm_bundles$ ls -l +total 388 +-rw-r--r-- 1 anisinha anisinha 199176 Aug 7 00:58 snptest.igvm +-rw-r--r-- 1 anisinha anisinha 195048 Aug 6 06:10 snptest-nohello.igvm + +Following files are used by the tests/qtest/launchupdate-test.c for non-co= co case: + +hello.igvm +qemuinit.igvm + +For confidential case (that is when COCO=3D1 is passed in the environment)= , the following +IGVM bundles are used: + +snptest-nohello.igvm +snptest.igvm + +The IGVM bundles used by the confidential case are not checked into the QE= MU +repository. Users who wish to test the confidential case can use the IGVM +bundles from https://gitlab.com/anisinha/virt-firmware-rs as mentioned abo= ve. diff --git a/tests/data/igvm/hello.igvm b/tests/data/igvm/hello.igvm new file mode 100644 index 0000000000000000000000000000000000000000..2d3ffda5b157c13d109ef965d1c= 0f41e9a34caf5 GIT binary patch literal 137112 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 s7( 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 Bl$8Jg literal 0 HcmV?d00001 --=20 2.55.0 From nobody Fri Aug 21 21:27:09 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1787328736; cv=none; d=zohomail.com; s=zohoarc; b=RNzpayOm3tCt5dPesQFFI76s+iiUlAecEA6lO+6Wu9gHGkTl/hFL2YZo3gwJpWlWDeuypKK3wrkgtJk+9QNF5sAgAoaWWE5jT5CLo5ZXdQdb+JjC45clnFj+NPuw6OrwLsvJOtRTK3ysElkfgsH2FQSPOCl2/HFLOGZfrRsInKo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787328736; 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=/8XQg6BQj4p/2z8ChYO9Qm5IxmkU3ohV5BRIh6gosgo=; b=RAWM/HngEf2CD8WtR9/yGyOmk8qN5TwVb4MfwMsyEWkI4ThOhQz7veaSw2sZZPO6raDKiGpDfQY76QktDzLEmBMc9LVTR0pgho5eaOV7gX0fD8vq6HX029NO4GpPBF3urONtnaP0S/U2CKfe7ER39BqMK5Fi67Ey5am7P+GUGQM= 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=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787328736422382.0182473341839; Fri, 21 Aug 2026 09:12:16 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wxRpz-0006Z0-Vv; Fri, 21 Aug 2026 12:11:24 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRpx-0006Xm-Qp for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:21 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRpu-0001ZH-5o for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:21 -0400 Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-378-J99oPZx7Pt-wooSZxQiALQ-1; Fri, 21 Aug 2026 12:11:13 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 1145A1954222; Fri, 21 Aug 2026 16:11:12 +0000 (UTC) Received: from sirius.home.kraxel.org (unknown [10.44.48.30]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 820371800346; Fri, 21 Aug 2026 16:11:11 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 378851801249; Fri, 21 Aug 2026 18:11:04 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787328677; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/8XQg6BQj4p/2z8ChYO9Qm5IxmkU3ohV5BRIh6gosgo=; b=RrOTCDAtidu6UGQNRjSKumjGMnbIlaUhFS1PqZ4Dbgo7PRVOMIoCLCICrKD1iE7ad55/8U Rl/yD6cT5pGXSOBMT+EwIHBsuEssvwMucvO3sBibo2+wb8drIfYpC8gwraIKV997B6s178 XwF9hvFwBkJ9sQNAY5q8T3YWQ0/Rnew= X-MC-Unique: J99oPZx7Pt-wooSZxQiALQ-1 X-Mimecast-MFC-AGG-ID: J99oPZx7Pt-wooSZxQiALQ_1787328672 From: Gerd Hoffmann To: qemu-devel@nongnu.org Cc: Ani Sinha , Cornelia Huck , Peter Maydell , Zhao Liu , Peter Xu , qemu-arm@nongnu.org, Pierrick Bouvier , Gerd Hoffman , "Michael S. Tsirkin" , Stefano Garzarella , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Laurent Vivier , Fabiano Rosas , Paolo Bonzini , Alex Graf Subject: [PULL 11/12] Add functional and unit tests for the vm-launch-update device Date: Fri, 21 Aug 2026 18:10:59 +0200 Message-ID: <20260821161103.3489298-12-kraxel@redhat.com> In-Reply-To: <20260821161103.3489298-1-kraxel@redhat.com> References: <20260821161103.3489298-1-kraxel@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 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=lists1p.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 9 X-Spam_score: 0.9 X-Spam_bar: / X-Spam_report: (0.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.341, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_SBL_CSS=3.335, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action 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 @redhat.com) X-ZM-MESSAGEID: 1787328738127158501 Content-Type: text/plain; charset="utf-8" From: Ani Sinha This patchset adds functional and unit tests that exercize various functions and behaviors of vm-launch-update device. It uses the IGVM files that were introduced in the previous patch for exercizing the hypervisor interface. CC: Alex Graf CC: Gerd Hoffman Reviewed-by: Alexander Graf Signed-off-by: Ani Sinha Message-ID: <20260817142010.80693-11-anisinha@redhat.com> Signed-off-by: Gerd Hoffmann --- .../aarch64/test_vm_launch_update_aarch.py | 33 + .../x86_64/test_vm_launch_update.py | 48 ++ tests/qtest/launchupdate-test.c | 625 ++++++++++++++++++ tests/functional/aarch64/meson.build | 4 + tests/functional/x86_64/meson.build | 4 + tests/qtest/meson.build | 2 + 6 files changed, 716 insertions(+) create mode 100755 tests/functional/aarch64/test_vm_launch_update_aarch.py create mode 100755 tests/functional/x86_64/test_vm_launch_update.py create mode 100644 tests/qtest/launchupdate-test.c diff --git a/tests/functional/aarch64/test_vm_launch_update_aarch.py b/test= s/functional/aarch64/test_vm_launch_update_aarch.py new file mode 100755 index 000000000000..2b3d7cf4a309 --- /dev/null +++ b/tests/functional/aarch64/test_vm_launch_update_aarch.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +# +# Check for vm-launch-update device. +# +# Copyright (c) 2026 Red Hat, Inc. +# +# Author: +# Ani Sinha +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import QemuSystemTest + +class VmLaunchUpdateDeviceCheck(QemuSystemTest): + + def aarch64_fail_test(self): + """ + Currently the device is only supported for pc platforms. + """ + self.vm.add_args('-machine', 'virt', '-device', + 'vm-launch-update,id=3Dfwupd1') + self.vm.set_qmp_monitor(enabled=3DFalse) + self.vm.launch() + self.vm.wait() + self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be = 1") + self.assertRegex(self.vm.get_log(), + r'This machine does not support vm-launch-update devic= e') + + def test_vm_launch_update(self): + self.aarch64_fail_test() + +if __name__ =3D=3D '__main__': + QemuSystemTest.main() diff --git a/tests/functional/x86_64/test_vm_launch_update.py b/tests/funct= ional/x86_64/test_vm_launch_update.py new file mode 100755 index 000000000000..aac7ef915f4e --- /dev/null +++ b/tests/functional/x86_64/test_vm_launch_update.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# +# Check for vm-launch-update device. +# +# Copyright (c) 2026 Red Hat, Inc. +# +# Author: +# Ani Sinha +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import QemuSystemTest +import time + +class VmLaunchUpdateDeviceCheck(QemuSystemTest): + DELAY_BOOT_SEQUENCE =3D 1 + + def vm_launch_update_pass(self): + """ + Basic test to make sure vm-launch-update device can be instantiate= d. + """ + self.vm.add_args('-device', 'vm-launch-update,id=3Dfwupd1') + self.vm.set_qmp_monitor(enabled=3DFalse) + self.vm.launch() + time.sleep(self.DELAY_BOOT_SEQUENCE) + self.vm.shutdown() + self.assertEqual(self.vm.exitcode(), 0, "QEMU exit code should be = 0") + + def multiple_device_fail(self): + """ + Only one vm-launch-update device can be instantiated. Ensure failu= re if + user tries to create more than one device. + """ + self.vm.add_args('-device', 'vm-launch-update,id=3Dfw1', + '-device', 'vm-launch-update,id=3Dfw2') + self.vm.set_qmp_monitor(enabled=3DFalse) + self.vm.launch() + self.vm.wait() + self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be = 1") + self.assertRegex(self.vm.get_log(), + r'at most one vm-launch-update device is permitte= d') + + def test_vm_launch_update(self): + self.vm_launch_update_pass() + self.multiple_device_fail() + +if __name__ =3D=3D '__main__': + QemuSystemTest.main() diff --git a/tests/qtest/launchupdate-test.c b/tests/qtest/launchupdate-tes= t.c new file mode 100644 index 000000000000..225c843df5b9 --- /dev/null +++ b/tests/qtest/launchupdate-test.c @@ -0,0 +1,625 @@ +/* + * vmlaunchupdate device fwcfg test. + * + * Copyright (c) 2026 Red Hat, Inc. + * + * Author: + * Ani Sinha + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "libqos/libqos-pc.h" +#include "libqtest.h" +#include "standard-headers/linux/qemu_fw_cfg.h" +#include "libqos/fw_cfg.h" +#include "qemu/bswap.h" +#include "hw/misc/vmlaunchupdate.h" + +#define WAIT_SEC 10 +static bool debug; +static bool trace; +static bool confidential; + +static void test_vm_launch_update_capability(void) +{ + QFWCFG *fw_cfg; + QTestState *s; + VMLaunchUpdate launch_update; + size_t filesize; + uint64_t capabilities; + + if (!qtest_has_device("vm-launch-update")) { + g_test_skip("Device vm-launch-update is not available"); + return; + } + + s =3D qtest_init("-device vm-launch-update"); + fw_cfg =3D pc_fw_cfg_init(s); + + filesize =3D qfw_cfg_get_file(fw_cfg, FILE_VMLAUNCHUPDATE, + &launch_update, sizeof(launch_update)); + g_assert_cmpint(filesize, =3D=3D, sizeof(launch_update)); + capabilities =3D le64_to_cpu(launch_update.capabilities); + g_assert_cmpint(capabilities, =3D=3D, VM_LAUNCHUPDATE_FORMAT_IGVM); + pc_fw_cfg_uninit(fw_cfg); + qtest_quit(s); +} + + +static void test_vm_launch_update_disable(void) +{ + QFWCFG *fw_cfg; + QOSState *qs; + VMLaunchUpdate launch_update; + uint64_t control; + size_t filesize; + + if (!qtest_has_device("vm-launch-update")) { + g_test_skip("Device vm-launch-update is not available"); + return; + } + + /* use default accelerator */ + qs =3D qtest_pc_boot("-device vm-launch-update"); + + fw_cfg =3D pc_fw_cfg_init(qs->qts); + + filesize =3D qfw_cfg_get_file(fw_cfg, FILE_VMLAUNCHUPDATE, + &launch_update, sizeof(launch_update)); + g_assert_cmpint(filesize, =3D=3D, sizeof(launch_update)); + control =3D le64_to_cpu(launch_update.control); + g_assert_cmpint(VM_LAUNCHUPDATE_CTL_DISABLE & control, =3D=3D, 0); + + /* disable the device */ + memset(&launch_update, 0, sizeof(launch_update)); + launch_update.control |=3D VM_LAUNCHUPDATE_CTL_DISABLE; + + filesize =3D qfw_cfg_write_file(fw_cfg, qs, FILE_VMLAUNCHUPDATE, + &launch_update, sizeof(launch_update)); + g_assert_cmpint(filesize, =3D=3D, sizeof(launch_update)); + + /* try to clear the dsable flag */ + memset(&launch_update, 0, sizeof(launch_update)); + + filesize =3D qfw_cfg_write_file(fw_cfg, qs, FILE_VMLAUNCHUPDATE, + &launch_update, sizeof(launch_update)); + g_assert_cmpint(filesize, =3D=3D, sizeof(launch_update)); + + /* check if the device is still disabled */ + filesize =3D qfw_cfg_get_file(fw_cfg, FILE_VMLAUNCHUPDATE, + &launch_update, sizeof(launch_update)); + g_assert_cmpint(filesize, =3D=3D, sizeof(launch_update)); + control =3D le64_to_cpu(launch_update.control); + g_assert_cmpint(VM_LAUNCHUPDATE_CTL_DISABLE & control, =3D=3D, 1); + + pc_fw_cfg_uninit(fw_cfg); + qtest_shutdown(qs); +} + +static void check_error(void) +{ + QFWCFG *fw_cfg; + QOSState *qs; + VMLaunchUpdate launch_update; + uint16_t status; + size_t filesize; + + if (!qtest_has_device("vm-launch-update")) { + g_test_skip("Device vm-launch-update is not available"); + return; + } + + /* guest not started with IGVM and with default accelerator */ + qs =3D qtest_pc_boot("-device vm-launch-update"); + + fw_cfg =3D pc_fw_cfg_init(qs->qts); + + memset(&launch_update, 0, sizeof(launch_update)); + launch_update.fw_image_size =3D 50; + launch_update.fw_image_addr =3D cpu_to_le64(0xdeadbeef); + launch_update.control |=3D VM_LAUNCHUPDATE_FORMAT_IGVM; + + filesize =3D qfw_cfg_write_file(fw_cfg, qs, FILE_VMLAUNCHUPDATE, + &launch_update, sizeof(launch_update)); + g_assert_cmpint(filesize, =3D=3D, sizeof(launch_update)); + + memset(&launch_update, 0, sizeof(launch_update)); + filesize =3D qfw_cfg_get_file(fw_cfg, FILE_VMLAUNCHUPDATE, + &launch_update, sizeof(launch_update)); + g_assert_cmpint(filesize, =3D=3D, sizeof(launch_update)); + status =3D le64_to_cpu(launch_update.status); + /* should fail with NOT_IGVM_INIT */ + g_assert_cmpint(status, =3D=3D, VM_LAUNCHUPDATE_NOT_IGVM_INIT); + + memset(&launch_update, 0, sizeof(launch_update)); + launch_update.fw_image_size =3D 50; + launch_update.fw_image_addr =3D cpu_to_le64(0xdeadbeef); + /* control set to 0, not VM_LAUNCHUPDATE_FORMAT_IGVM */ + + filesize =3D qfw_cfg_write_file(fw_cfg, qs, FILE_VMLAUNCHUPDATE, + &launch_update, sizeof(launch_update)); + g_assert_cmpint(filesize, =3D=3D, sizeof(launch_update)); + + memset(&launch_update, 0, sizeof(launch_update)); + filesize =3D qfw_cfg_get_file(fw_cfg, FILE_VMLAUNCHUPDATE, + &launch_update, sizeof(launch_update)); + g_assert_cmpint(filesize, =3D=3D, sizeof(launch_update)); + status =3D le64_to_cpu(launch_update.status); + /* should fail with LOAD_FAIL since it was not IGVM format */ + g_assert_cmpint(status, =3D=3D, VM_LAUNCHUPDATE_LOAD_FAIL); +} + +static int64_t get_image_size(const char *filename) +{ + int fd; + int64_t size; + fd =3D open(filename, O_RDONLY | O_BINARY); + g_assert_true(fd > 0); + size =3D lseek(fd, 0, SEEK_END); + close(fd); + return size; +} + +static ssize_t load_image(const char *igvm_f, void **addr, size_t *size) +{ + ssize_t actsize =3D 0, l =3D 0; + int f_igvm_f; + size_t l_size; + + f_igvm_f =3D open(igvm_f, O_RDONLY | O_BINARY); + g_assert_true(f_igvm_f); + l_size =3D get_image_size(igvm_f); + g_assert_true(l_size > 0); + *addr =3D g_malloc0(l_size); + g_assert_true(*addr); + + while (l < l_size) { + actsize =3D read(f_igvm_f, *addr + l, 1); + if (actsize < 0) { + break; + } + l +=3D actsize; + } + + close(f_igvm_f); + *size =3D l_size; + return actsize < 0 ? -1 : l; +} + +static guint32 match_string(char *serial_f, const char *exp_out) +{ + GError *error =3D NULL; + g_autofree gchar *f_contents =3D NULL; + g_autofree GRegex *regex =3D NULL; + g_autofree GMatchInfo *match_info =3D NULL; + gsize len; + guint32 count =3D 0; + gboolean ret; + + ret =3D g_file_get_contents(serial_f, &f_contents, &len, &error); + g_assert(ret); + g_assert_no_error(error); + + regex =3D g_regex_new(exp_out, G_REGEX_CASELESS, 0, &error); + g_assert_no_error(error); + + ret =3D g_regex_match_full(regex, f_contents, -1, 0, 0, &match_info, &= error); + g_assert_no_error(error); + + while (g_match_info_matches(match_info)) { + gchar *word =3D g_match_info_fetch(match_info, 0); + g_free(word); + g_match_info_next(match_info, &error); + count++; + } + g_regex_unref(regex); + return count; +} + +static int wait_for_match(char *serial_f, + const char *exp_out, int64_t timeout_s, + guint32 count) +{ + time_t start, delta; + int ret =3D -1; + + start =3D time(NULL); + while (1) { + if (match_string(serial_f, exp_out) =3D=3D count) { + ret =3D 0; + break; + } + + delta =3D time(NULL) - start; + if (delta >=3D timeout_s) { + fprintf(stderr, "timed out waiting to read serial output\n"); + break; + } + + /* wait 20 ms before trying again */ + if (false) { + fprintf(stderr, + "sleeping 20 ms before checking serial output again.\n= "); + } + g_usleep(20000); + } + return ret; +} + +static void set_test_params(const char **igvm_f, const char **igvm_init, + const char **snp, const char **cgs) +{ + if (confidential) { + *snp =3D "-object \'{\"qom-type\":\"sev-snp-guest\",\"id\":\"lsec0= \"," + "\"cbitpos\":51,\"reduced-phys-bits\":1,\"policy\":196608}\'"; + *cgs =3D "confidential-guest-support=3Dlsec0"; + /* + * The following two IGVM files can be built from the source + * present in https://gitlab.com/anisinha/virt-firmware-rs . + * Typing 'make' from the top of this repository will build the + * IGVM files for both confidential and + * non-confidential tests. The IGVM files for the non-coco + * case has been checked-in into the QEMU repository for + * convenience and easy CI pipeline testing. + */ + *igvm_f =3D "tests/data/igvm/snptest.igvm"; /* prints 'hello world= ' */ + *igvm_init =3D "tests/data/igvm/snptest-nohello.igvm"; + } else { + *igvm_f =3D "tests/data/igvm/hello.igvm"; + *igvm_init =3D "tests/data/igvm/qemuinit.igvm"; + *snp =3D ""; + *cgs =3D ""; + } + + return; +} + +static void set_expected_out(const char **exp_out, const char **exp_out2, + const char **exp_out3) +{ + *exp_out =3D "Hello world!"; + *exp_out2 =3D "Test succeeded!"; + *exp_out3 =3D "boot process complete with initial igvm"; + + return; +} + +static QOSState *set_qemu_args(const char *cgs, const char *tp, char *seri= alf, + const char *igvm_init, const char *snp) +{ + QOSState *qs; + + if (tp) { + qs =3D qtest_pc_boot("-machine q35,igvm-cfg=3Digvm0,%s -m 1G -acce= l kvm " + "-device vm-launch-update %s " + "-chardev file,id=3Dserial0,path=3D%s " + "-serial chardev:serial0 " + "-object igvm-cfg,id=3Digvm0,file=3D%s %s", + cgs, tp, serialf, igvm_init, snp); + } else { + qs =3D qtest_pc_boot("-machine q35,igvm-cfg=3Digvm0,%s -m 1G -acce= l kvm " + "-device vm-launch-update " + "-chardev file,id=3Dserial0,path=3D%s " + "-serial chardev:serial0 " + "-object igvm-cfg,id=3Digvm0,file=3D%s %s", + cgs, serialf, igvm_init, snp); + } + + return qs; +} + +static void test_load_igvm(void) +{ + const char *igvm_f; + const char *igvm_init; + int ser_fd; + g_autofree void *igvm_blob =3D NULL; + g_autofree char *serialtmp =3D NULL; + const char *exp_out; + const char *exp_out2; + const char *exp_out3; + const char *tracepoints =3D "--trace memory_region_finalize " + "--trace qigvm_cleanup_memory -D /tmp/qemu-debug.log "; + const char *snp, *cgs; + uint64_t gaddr; + size_t igvm_sz; + size_t filesize; + QFWCFG *fw_cfg; + QOSState *qs; + VMLaunchUpdate launch_update; + + if (!trace) { + tracepoints =3D ""; + } + + if (!qtest_has_machine("q35")) { + g_test_skip("q35 machine not available"); + return; + } + + if (!qtest_has_accel("kvm")) { + g_test_skip("No KVM accelerator available"); + return; + } + + if (!qtest_has_device("vm-launch-update")) { + g_test_skip("Device vm-launch-update is not available"); + return; + } + + set_test_params(&igvm_f, &igvm_init, &snp, &cgs); + set_expected_out(&exp_out, &exp_out2, &exp_out3); + + if (!g_file_test(igvm_f, G_FILE_TEST_EXISTS) || + !g_file_test(igvm_init, G_FILE_TEST_EXISTS)) { + g_test_skip("igvm file bundle(s) does not exist!"); + return; + } + + ser_fd =3D g_file_open_tmp("launchupdate-qtest-serial-sXXXXXX", + &serialtmp, NULL); + g_assert_true(ser_fd !=3D -1); + + if (debug) { + fprintf(stderr, "serial console file is %s\n", serialtmp); + } + + qs =3D set_qemu_args(cgs, tracepoints, serialtmp, igvm_init, snp); + + fw_cfg =3D pc_fw_cfg_init(qs->qts); + + if (debug) { + fprintf(stderr, "target endianness: %s\n", + qtest_big_endian(qs->qts) ? "big" : "little"); + } + + /* exp_out3 should be printed once from initial boot */ + g_assert_true(wait_for_match(serialtmp, exp_out3, WAIT_SEC, 1) =3D=3D = 0); + + if (debug) { + fprintf(stderr, "initially booted with host igvm\n"); + } + + g_assert_true(load_image(igvm_f, &igvm_blob, &igvm_sz) =3D=3D igvm_sz); + + /* create a data buffer in guest memory */ + gaddr =3D guest_alloc(&qs->alloc, igvm_sz); + + if (debug) { + fprintf(stderr, "guest paddr: %"PRIx64 " igvm size: %lu\n", + gaddr, igvm_sz); + } + + if (debug) { + fprintf(stderr, "writing igvm file into the guest memory\n"); + } + + qtest_bufwrite(qs->qts, gaddr, igvm_blob, igvm_sz); + + if (debug) { + fprintf(stderr, + "tell hypervisor where igvm is loaded in guest memory\n"); + } + + /* now tell hypervisor where we loaded the bios */ + memset(&launch_update, 0, sizeof(launch_update)); + launch_update.fw_image_size =3D cpu_to_le64(igvm_sz); + launch_update.fw_image_addr =3D cpu_to_le64(gaddr); + launch_update.control |=3D VM_LAUNCHUPDATE_FORMAT_IGVM; + + filesize =3D qfw_cfg_write_file(fw_cfg, qs, FILE_VMLAUNCHUPDATE, + &launch_update, sizeof(launch_update)); + g_assert_cmpint(filesize, =3D=3D, sizeof(launch_update)); + + if (debug) { + fprintf(stderr, "resetting the virtual machine now\n"); + } + + qtest_system_reset(qs->qts); + + /* expected string should be printed on the console */ + g_assert_true(wait_for_match(serialtmp, exp_out, WAIT_SEC, 1) =3D=3D 0= ); + g_assert_true(wait_for_match(serialtmp, exp_out2, WAIT_SEC, 1) =3D=3D = 0); + + if (debug) { + fprintf(stderr, "hello world found on console\n"); + } + + /* check if VM_LAUNCHUPDATE_CTL_HOST_IGVM function works */ + + /* set only VM_LAUNCHUPDATE_CTL_HOST_IGVM control without IGVM bundle = */ + memset(&launch_update, 0, sizeof(launch_update)); + launch_update.control |=3D VM_LAUNCHUPDATE_CTL_HOST_IGVM; + + filesize =3D qfw_cfg_write_file(fw_cfg, qs, FILE_VMLAUNCHUPDATE, + &launch_update, sizeof(launch_update)); + g_assert_cmpint(filesize, =3D=3D, sizeof(launch_update)); + + /* now reset the guest */ + if (debug) { + fprintf(stderr, + "resetting again in order to restore host provided IGVM\n"= ); + } + qtest_system_reset(qs->qts); + + /* + * exp_out3 should be printed twice, once from initial boot, + * once from restoring host igvm. + */ + g_assert_true(wait_for_match(serialtmp, exp_out3, WAIT_SEC, 2) =3D=3D = 0); + + if (debug) { + fprintf(stderr, "booted with host igvm again\n"); + } + + close(ser_fd); + guest_free(&qs->alloc, gaddr); + pc_fw_cfg_uninit(fw_cfg); + /* qtest_quit() kils QEMU, first by sending SIGTERM, then SIGKILL */ + qtest_quit(qs->qts); +} + +static void test_set_ctrl_once_and_reset_to_host_igvm(void) +{ + const char *igvm_f; + const char *igvm_init; + int ser_fd; + g_autofree void *igvm_blob =3D NULL; + g_autofree char *serialtmp =3D NULL; + const char *exp_out; + const char *exp_out2; + const char *exp_out3; + const char *snp, *cgs; + uint64_t gaddr; + size_t igvm_sz; + size_t filesize; + QFWCFG *fw_cfg; + QOSState *qs; + VMLaunchUpdate launch_update; + + if (!qtest_has_machine("q35")) { + g_test_skip("q35 machine not available"); + return; + } + + if (!qtest_has_accel("kvm")) { + g_test_skip("No KVM accelerator available"); + return; + } + + if (!qtest_has_device("vm-launch-update")) { + g_test_skip("Device vm-launch-update is not available"); + return; + } + + set_test_params(&igvm_f, &igvm_init, &snp, &cgs); + set_expected_out(&exp_out, &exp_out2, &exp_out3); + + if (!g_file_test(igvm_f, G_FILE_TEST_EXISTS) || + !g_file_test(igvm_init, G_FILE_TEST_EXISTS)) { + g_test_skip("igvm file bundle(s) does not exist!"); + return; + } + + ser_fd =3D g_file_open_tmp("launchupdate-qtest-serial-sXXXXXX", + &serialtmp, NULL); + g_assert_true(ser_fd !=3D -1); + + if (debug) { + fprintf(stderr, "serial console file is %s\n", serialtmp); + } + + qs =3D set_qemu_args(cgs, NULL, serialtmp, igvm_init, snp); + + fw_cfg =3D pc_fw_cfg_init(qs->qts); + + g_assert_true(wait_for_match(serialtmp, exp_out3, WAIT_SEC, 1) =3D=3D = 0); + + if (debug) { + fprintf(stderr, "initially booted with host igvm\n"); + } + + g_assert_true(load_image(igvm_f, &igvm_blob, &igvm_sz) =3D=3D igvm_sz); + + /* create a data buffer in guest memory */ + gaddr =3D guest_alloc(&qs->alloc, igvm_sz); + + if (debug) { + fprintf(stderr, "guest paddr: %"PRIx64 " igvm size: %lu\n", + gaddr, igvm_sz); + } + + if (debug) { + fprintf(stderr, "writing igvm file into the guest memory\n"); + } + + qtest_bufwrite(qs->qts, gaddr, igvm_blob, igvm_sz); + + if (debug) { + fprintf(stderr, + "tell hypervisor where igvm is loaded in guest memory\n"); + } + + /* now tell hypervisor where we loaded the bios */ + memset(&launch_update, 0, sizeof(launch_update)); + launch_update.fw_image_size =3D cpu_to_le64(igvm_sz); + launch_update.fw_image_addr =3D cpu_to_le64(gaddr); + + /* set both host ctrl and format_igvm ctrl once */ + launch_update.control |=3D VM_LAUNCHUPDATE_FORMAT_IGVM; + launch_update.control |=3D VM_LAUNCHUPDATE_CTL_HOST_IGVM; + + filesize =3D qfw_cfg_write_file(fw_cfg, qs, FILE_VMLAUNCHUPDATE, + &launch_update, sizeof(launch_update)); + g_assert_cmpint(filesize, =3D=3D, sizeof(launch_update)); + + if (debug) { + fprintf(stderr, "resetting the virtual machine. This should load " + "user provided igvm.\n"); + } + + qtest_system_reset(qs->qts); + + /* expected string should be printed on the console */ + g_assert_true(wait_for_match(serialtmp, exp_out, WAIT_SEC, 1) =3D=3D 0= ); + g_assert_true(wait_for_match(serialtmp, exp_out2, WAIT_SEC, 1) =3D=3D = 0); + + if (debug) { + fprintf(stderr, "hello world found on console\n"); + fprintf(stderr, "Now resetting again in order to reset to host igv= m\n"); + } + + qtest_system_reset(qs->qts); + + /* + * exp_out3 should be printed twice, once from initial boot, + * once from restoring host igvm. + */ + g_assert_true(wait_for_match(serialtmp, exp_out3, WAIT_SEC, 2) =3D=3D = 0); + + if (debug) { + fprintf(stderr, "booted with host igvm\n"); + } + + close(ser_fd); + guest_free(&qs->alloc, gaddr); + pc_fw_cfg_uninit(fw_cfg); + /* qtest_quit() kils QEMU, first by sending SIGTERM, then SIGKILL */ + qtest_quit(qs->qts); +} + +int main(int argc, char **argv) +{ + const char *arch =3D qtest_get_arch(); + + g_test_init(&argc, &argv, NULL); + + if (strcmp(arch, "x86_64")) { + g_test_skip("vmlaunchupdate tests are only available on x86_64\n"); + return 0; + } + + g_test_add_func("/vm-launch-update/cap", test_vm_launch_update_capabil= ity); + g_test_add_func("/vm-launch-update/disabled", + test_vm_launch_update_disable); + + g_test_add_func("/vm-launch-update/errorcheck", check_error); + g_test_add_func("/vm-launch-update/load_igvm", + test_load_igvm); + g_test_add_func("/vm-launch-update/ctrl_set_once", + test_set_ctrl_once_and_reset_to_host_igvm); + + if (getenv("LAUNCHUPDATE_DEBUG")) { + debug =3D true; + } + if (getenv("LAUNCHUPDATE_TRACE")) { + trace =3D true; + } + if (getenv("COCO")) { + confidential =3D true; + } + + return g_test_run(); +} diff --git a/tests/functional/aarch64/meson.build b/tests/functional/aarch6= 4/meson.build index e81afd6c39fc..f0881bed1671 100644 --- a/tests/functional/aarch64/meson.build +++ b/tests/functional/aarch64/meson.build @@ -25,6 +25,10 @@ tests_aarch64_system_quick =3D [ 'vmstate', ] =20 +if igvm.found() + tests_aarch64_system_quick +=3D [ 'vm_launch_update_aarch' ] +endif + tests_aarch64_system_thorough =3D [ 'aspeed_ast2700a1', 'aspeed_ast2700a2', diff --git a/tests/functional/x86_64/meson.build b/tests/functional/x86_64/= meson.build index 27b31f2e966f..0353b2af8e1d 100644 --- a/tests/functional/x86_64/meson.build +++ b/tests/functional/x86_64/meson.build @@ -28,6 +28,10 @@ if not get_option('asan') tests_x86_64_system_quick +=3D [ 'memlock' ] endif =20 +if igvm.found() + tests_x86_64_system_quick +=3D [ 'vm_launch_update' ] +endif + tests_x86_64_system_thorough =3D [ 'acpi_bits', 'hotplug_blk', diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index f7c7d06620ea..12ed368997b6 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -61,6 +61,8 @@ qtests_i386 =3D \ (config_all_devices.has_key('CONFIG_Q35') ? ['e820-test'] : []) + = \ (config_all_devices.has_key('CONFIG_FW_CFG_DMA') ? ['vmcoreinfo-test'] := []) + \ (config_all_devices.has_key('CONFIG_Q35') ? ['dump-test'] : []) + = \ + (igvm.found() and + config_all_devices.has_key('CONFIG_FW_CFG_DMA') ? ['launchupdate-test']= : []) + \ (config_all_devices.has_key('CONFIG_I440FX') ? ['i440fx-test'] : []) + = \ (config_all_devices.has_key('CONFIG_I440FX') ? ['ide-test'] : []) + = \ (config_all_devices.has_key('CONFIG_I440FX') ? ['numa-test'] : []) + = \ --=20 2.55.0 From nobody Fri Aug 21 21:27:09 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1787328815; cv=none; d=zohomail.com; s=zohoarc; b=JKcM6rI/GgyFTcims4sCvYMv78Xex6bRbocd4ppzxNWfYsdLiAevtL9csKSX0FXd+f2lRlkM+EroAX1Kli52V9MUedv3lj0gB3Luimv7p9H+B610PDZXgdpvpvaAxCeAvDZrYf4hVLi5wRMnYMSFYOLhz/T1/tDsHAFzWrVRm4Y= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787328815; h=Content-Type: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=FiHebt2K8ov/fB/KWfyWW+Ff1zEX9PPLHSk7DxO9ZPI=; b=SsHtzGeOMGkaOPW2YXWRQ7yk6pchMI3MOJtUCKYnsaAFWB0mVbZz5rEfqtSH5I1gDd8Bh8UFp299ucjrpBhIjRjbMWYlgbUkrSfKU/1nmxCiQOEHT3GDsHd1igEHqwwDKvgfr5kY/eSourtGPMZdSm97unv91oNcypxVQmQ08qg= 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=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787328815197867.8260081142148; Fri, 21 Aug 2026 09:13:35 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wxRpy-0006YI-Ou; Fri, 21 Aug 2026 12:11:22 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRpw-0006WT-3Z for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:20 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wxRpu-0001ZV-BP for qemu-devel@nongnu.org; Fri, 21 Aug 2026 12:11:19 -0400 Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-661-7RPysQJ3MI6tH6DU7EZieg-1; Fri, 21 Aug 2026 12:11:14 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id CC40B1954AE9; Fri, 21 Aug 2026 16:11:12 +0000 (UTC) Received: from sirius.home.kraxel.org (unknown [10.44.48.30]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 8531C18005BD; Fri, 21 Aug 2026 16:11:12 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 47229180124A; Fri, 21 Aug 2026 18:11:04 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787328677; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=FiHebt2K8ov/fB/KWfyWW+Ff1zEX9PPLHSk7DxO9ZPI=; b=Ifz+ikupoOhN8ThHl+LfYe6bY4t8UOlJcMc65u0vU/iXtiuNieadxQWK4Q0YDsgpTHNUQe yVTAf6xBhDVISg4UyaJseYictX9VLxYtN09L3QFjhrT3AohJBi50+nKqeHaTkSgtZBcSeM lKHL1OKoz6t5lLqCEBCvXwBmg6gOZHA= X-MC-Unique: 7RPysQJ3MI6tH6DU7EZieg-1 X-Mimecast-MFC-AGG-ID: 7RPysQJ3MI6tH6DU7EZieg_1787328672 From: Gerd Hoffmann To: qemu-devel@nongnu.org Cc: Ani Sinha , Cornelia Huck , Peter Maydell , Zhao Liu , Peter Xu , qemu-arm@nongnu.org, Pierrick Bouvier , Gerd Hoffman , "Michael S. Tsirkin" , Stefano Garzarella , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Laurent Vivier , Fabiano Rosas , Paolo Bonzini , Alexander Graf Subject: [PULL 12/12] Update MAINTAINERS Date: Fri, 21 Aug 2026 18:11:00 +0200 Message-ID: <20260821161103.3489298-13-kraxel@redhat.com> In-Reply-To: <20260821161103.3489298-1-kraxel@redhat.com> References: <20260821161103.3489298-1-kraxel@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 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=lists1p.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 9 X-Spam_score: 0.9 X-Spam_bar: / X-Spam_report: (0.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.341, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=0.001, RCVD_IN_SBL_CSS=3.335, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action 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 @redhat.com) X-ZM-MESSAGEID: 1787328816338158500 From: Ani Sinha Add maintainers for vm-launch-update device and associated documentation and test code. Reviewed-by: Alexander Graf Signed-off-by: Ani Sinha Message-ID: <20260817142010.80693-12-anisinha@redhat.com> Signed-off-by: Gerd Hoffmann --- MAINTAINERS | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 9e0a2a656f4c..1f9c08d76601 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2851,6 +2851,19 @@ F: include/hw/acpi/vmgenid.h F: docs/specs/vmgenid.rst F: tests/qtest/vmgenid-test.c =20 +VM Launch Update +M: Ani Sinha +M: Gerd Hoffman +S: Maintained +F: hw/misc/vmlaunchupdate.c +F: include/hw/misc/vmlaunchupdate.h +F: include/standard-headers/misc/vmlaunchupdate.h +F: docs/specs/vmlaunchupdate.rst +F: tests/functional/aarch64/test_vm_launch_update_aarch.py +F: tests/functional/x86_64/test_vm_launch_update.py +F: tests/qtest/launchupdate-test.c +F: tests/data/igvm/* + LED M: Philippe Mathieu-Daud=C3=A9 S: Maintained --=20 2.55.0