From nobody Sun Feb 8 12:32:34 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass header.i=@amazon.es; 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=amazon.es ARC-Seal: i=1; a=rsa-sha256; t=1659538747; cv=none; d=zohomail.com; s=zohoarc; b=mUiWA3/VEDXmETASlDOVVYXJTvtOc6XLe14hqcLYHV+mQUcjsAUL6kALrbgzQK+hKUBYOklWHtm3D1p4HyFVTcwdArEU35Rtrt6Y2G1gW+r33BOwuRh48RFz+ZnsNQt6i6ftbNpLufUMr1d9Slxi6eZxWHf0pEuEaYHzK2bU/pc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1659538747; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=QXYz39LWwKXIzjCNr/W99HiCY8msg68JHOXOlUPq+ZY=; b=kCXdbXW/tgx+UmUaoCth1oMo6FAi1dPFWIKqGQ22jGtqp0NGMcQ2qpwcQ6x4ZaKj+mp/Hf9UDCp+t4SoIW/m9wCIRAobr0CgCjZiyLcoyTEZA7FzYtYb3EkTeLCI/dQeN8JOBbJObDCx46IqTqKCWVKyz5uPXenJiMsHKC1wIVc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=@amazon.es; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1659538747793844.6090149026592; Wed, 3 Aug 2022 07:59:07 -0700 (PDT) Received: from localhost ([::1]:59504 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oJFpy-00077P-PR for importer@patchew.org; Wed, 03 Aug 2022 10:59:06 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55190) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oJEdy-0005QW-1j for qemu-devel@nongnu.org; Wed, 03 Aug 2022 09:42:38 -0400 Received: from smtp-fw-6001.amazon.com ([52.95.48.154]:58719) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oJEdu-00047P-7a for qemu-devel@nongnu.org; Wed, 03 Aug 2022 09:42:37 -0400 Received: from iad12-co-svc-p1-lb1-vlan2.amazon.com (HELO email-inbound-relay-iad-1a-2d7489a4.us-east-1.amazon.com) ([10.43.8.2]) by smtp-border-fw-6001.iad6.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Aug 2022 13:42:19 +0000 Received: from EX13D37EUA003.ant.amazon.com (iad12-ws-svc-p26-lb9-vlan2.iad.amazon.com [10.40.163.34]) by email-inbound-relay-iad-1a-2d7489a4.us-east-1.amazon.com (Postfix) with ESMTPS id 0609584333; Wed, 3 Aug 2022 13:42:17 +0000 (UTC) Received: from f4d4887fdcfb.ant.amazon.com (10.43.162.227) by EX13D37EUA003.ant.amazon.com (10.43.165.7) with Microsoft SMTP Server (TLS) id 15.0.1497.36; Wed, 3 Aug 2022 13:42:13 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.es; i=@amazon.es; q=dns/txt; s=amazon201209; t=1659534154; x=1691070154; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=QXYz39LWwKXIzjCNr/W99HiCY8msg68JHOXOlUPq+ZY=; b=cSIHYmaoSjcct8OEMpxqiuJDV4xY/T5ykhPLIRVpajKrtARujIBbR3uM YxFUe4etT4kfRukI3eqZHsvjGBwKrZM4WGUsR+KopeBLKo6NCPNxA+sfH fP+TapeCq4tAV/+/H1AEkUnn9bvbYVx4EMVICIHB8J+73DUlMRWwUqdXx Y=; From: To: CC: , , , , , , Subject: [PATCH 1/2] vmgenid: make device data size configurable Date: Wed, 3 Aug 2022 15:41:46 +0200 Message-ID: <20220803134147.31073-2-bchalios@amazon.es> X-Mailer: git-send-email 2.32.1 (Apple Git-133) In-Reply-To: <20220803134147.31073-1-bchalios@amazon.es> References: <20220803134147.31073-1-bchalios@amazon.es> MIME-Version: 1.0 X-Originating-IP: [10.43.162.227] X-ClientProxiedBy: EX13D41UWC002.ant.amazon.com (10.43.162.127) To EX13D37EUA003.ant.amazon.com (10.43.165.7) Precedence: Bulk Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=52.95.48.154; envelope-from=prvs=207aa399e=bchalios@amazon.es; helo=smtp-fw-6001.amazon.com X-Spam_score_int: -44 X-Spam_score: -4.5 X-Spam_bar: ---- X-Spam_report: (-4.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.082, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Wed, 03 Aug 2022 10:54:38 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @amazon.es) X-ZM-MESSAGEID: 1659538748457100001 Content-Type: text/plain; charset="utf-8" From: Babis Chalios When allocating memory for the device data the assumption is we are dealing with 4K pages. Make this configurable, so that other architectures can be handled. Note, than in the original spec this is not a requirement, however, it is useful for implementing the generation counter (see next commit in this patchset) in architectures with page sizes other than 4K. Signed-off-by: Babis Chalios --- docs/specs/vmgenid.txt | 8 +++--- hw/acpi/vmgenid.c | 57 ++++++++++++++++++++++++++++++++++++--- include/hw/acpi/vmgenid.h | 14 +++++----- 3 files changed, 66 insertions(+), 13 deletions(-) diff --git a/docs/specs/vmgenid.txt b/docs/specs/vmgenid.txt index 80ff69f31c..5274b4c895 100644 --- a/docs/specs/vmgenid.txt +++ b/docs/specs/vmgenid.txt @@ -225,14 +225,16 @@ following diagram: Device Usage: ------------- =20 -The device has one property, which may be only be set using the command li= ne: +The device has two properties, which may be only be set using the command = line: =20 - guid - sets the value of the GUID. A special value "auto" instructs + guid - sets the value of the GUID. A special value "auto" instructs QEMU to generate a new random GUID. + page-size - sets the target machines page size. Currently accepted values + are 4096 (default) and 65536. =20 For example: =20 - QEMU -device vmgenid,guid=3D"324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87" + QEMU -device vmgenid,guid=3D"324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87",page= -size=3D65536 QEMU -device vmgenid,guid=3Dauto =20 The property may be queried via QMP/HMP: diff --git a/hw/acpi/vmgenid.c b/hw/acpi/vmgenid.c index 0c9f158ac9..ac2b116b6a 100644 --- a/hw/acpi/vmgenid.c +++ b/hw/acpi/vmgenid.c @@ -11,6 +11,7 @@ */ =20 #include "qemu/osdep.h" +#include "qapi/visitor.h" #include "qapi/error.h" #include "qapi/qapi-commands-machine.h" #include "qemu/module.h" @@ -35,7 +36,7 @@ void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_= data, GArray *guid, /* Fill in the GUID values. These need to be converted to little-endi= an * first, since that's what the guest expects */ - g_array_set_size(guid, VMGENID_FW_CFG_SIZE - ARRAY_SIZE(guid_le.data)); + g_array_set_size(guid, vms->page_size - ARRAY_SIZE(guid_le.data)); guid_le =3D qemu_uuid_bswap(vms->guid); /* The GUID is written at a fixed offset into the fw_cfg file * in order to implement the "OVMF SDT Header probe suppressor" @@ -94,7 +95,8 @@ void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_= data, GArray *guid, g_array_append_vals(table_data, ssdt->buf->data, ssdt->buf->len); =20 /* Allocate guest memory for the Data fw_cfg blob */ - bios_linker_loader_alloc(linker, VMGENID_GUID_FW_CFG_FILE, guid, 4096, + bios_linker_loader_alloc(linker, VMGENID_GUID_FW_CFG_FILE, guid, + vms->page_size, false /* page boundary, high memory */); =20 /* Patch address of GUID fw_cfg blob into the ADDR fw_cfg blob @@ -124,8 +126,7 @@ void vmgenid_build_acpi(VmGenIdState *vms, GArray *tabl= e_data, GArray *guid, void vmgenid_add_fw_cfg(VmGenIdState *vms, FWCfgState *s, GArray *guid) { /* Create a read-only fw_cfg file for GUID */ - fw_cfg_add_file(s, VMGENID_GUID_FW_CFG_FILE, guid->data, - VMGENID_FW_CFG_SIZE); + fw_cfg_add_file(s, VMGENID_GUID_FW_CFG_FILE, guid->data, vms->page_siz= e); /* Create a read-write fw_cfg file for Address */ fw_cfg_add_file_callback(s, VMGENID_ADDR_FW_CFG_FILE, NULL, NULL, NULL, vms->vmgenid_addr_le, @@ -215,8 +216,56 @@ static void vmgenid_realize(DeviceState *dev, Error **= errp) vmgenid_update_guest(vms); } =20 +static void get_page_size(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + Property *prop =3D opaque; + uint32_t *page_size =3D object_field_prop_ptr(obj, prop); + + visit_type_uint32(v, name, page_size, errp); +} + +static void set_page_size(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + Property *prop =3D opaque; + uint32_t *page_size =3D object_field_prop_ptr(obj, prop); + uint32_t val; + char str[10]; + + if (!visit_type_uint32(v, name, &val, errp)) { + return; + } + + switch (val) { + case 4096: + case 65536: + *page_size =3D val; + break; + default: + snprintf(str, 10, "%d", val); + error_set_from_qdev_prop_error(errp, EINVAL, obj, name, str); + } +} + +static void set_default_page_size(ObjectProperty *op, const Property *prop) +{ + object_property_set_default_uint(op, VMGENID_DEFAULT_FW_PAGE_SIZE); +} + +const PropertyInfo vmgenid_prop_page_size =3D { + .name =3D "uint32", + .description =3D "Page size to use for allocating device memory. \"" + "\"Valid values: 4096(default) 65536", + .get =3D get_page_size, + .set =3D set_page_size, + .set_default_value =3D set_default_page_size, +}; + static Property vmgenid_device_properties[] =3D { DEFINE_PROP_UUID(VMGENID_GUID, VmGenIdState, guid), + DEFINE_PROP_UNSIGNED(VMGENID_PAGE_SIZE, VmGenIdState, page_size, 0, + vmgenid_prop_page_size, uint32_t), DEFINE_PROP_END_OF_LIST(), }; =20 diff --git a/include/hw/acpi/vmgenid.h b/include/hw/acpi/vmgenid.h index dc8bb3433e..e4d83f5c74 100644 --- a/include/hw/acpi/vmgenid.h +++ b/include/hw/acpi/vmgenid.h @@ -6,15 +6,16 @@ #include "qemu/uuid.h" #include "qom/object.h" =20 -#define TYPE_VMGENID "vmgenid" -#define VMGENID_GUID "guid" +#define TYPE_VMGENID "vmgenid" +#define VMGENID_GUID "guid" +#define VMGENID_PAGE_SIZE "page-size" #define VMGENID_GUID_FW_CFG_FILE "etc/vmgenid_guid" #define VMGENID_ADDR_FW_CFG_FILE "etc/vmgenid_addr" =20 -#define VMGENID_FW_CFG_SIZE 4096 /* Occupy a page of memory */ -#define VMGENID_GUID_OFFSET 40 /* allow space for - * OVMF SDT Header Probe Supressor - */ +#define VMGENID_DEFAULT_FW_PAGE_SIZE 4096 /* Assume 4K page by default */ +#define VMGENID_GUID_OFFSET 40 /* allow space for OVMF SDT Hea= der + * Probe Supressor + */ =20 OBJECT_DECLARE_SIMPLE_TYPE(VmGenIdState, VMGENID) =20 @@ -22,6 +23,7 @@ struct VmGenIdState { DeviceState parent_obj; QemuUUID guid; /* The 128-bit GUID seen by the guest */ uint8_t vmgenid_addr_le[8]; /* Address of the GUID (little-endian) */ + uint32_t page_size; /* Page size to use as a the allocation = unit */ }; =20 /* returns NULL unless there is exactly one device */ --=20 2.32.1 (Apple Git-133) Amazon Spain Services sociedad limitada unipersonal, Calle Ramirez de Prado= 5, 28045 Madrid. Registro Mercantil de Madrid . Tomo 22458 . Folio 102 . H= oja M-401234 . CIF B84570936 From nobody Sun Feb 8 12:32:34 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass header.i=@amazon.es; 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=amazon.es ARC-Seal: i=1; a=rsa-sha256; t=1659538667; cv=none; d=zohomail.com; s=zohoarc; b=jQH+yvaUitxB3Vf/HK1ROEEPhRR51Ud1nKNeNGHROxgK/C6f5Sbq0PjjIT1U2Q+Ca64ikDGxzNK0kOj+Moz9IXXEHTEfEl/GP6oKQ6oyYKNuoOnEXhDlpu2Z7uuxolbxe4GcpFtCxEmBuqJkonj8wTXTTUNYYLFN/FguYH9aTJU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1659538667; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=x98uMoxWp5rgjNFDMbf+krw72BDczBR2Qf1VC9TcJC0=; b=DBYEJv0dN0gIzaowIu31k1/52Y2l/OkoHMjk9uol2QAWxZV89RHQ+bRC0ml/+bXOlsnwqZE/iY7+8/hgZSXkurvzHK/4sz4I9VQSuW/yD41Au7bz10w5M0/u4u+Jm1Q21UFviurKZguaMGJ+W5BV7XTSGKxdE1xpHB2ihtkV0OM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=@amazon.es; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1659538667450397.9410213801324; Wed, 3 Aug 2022 07:57:47 -0700 (PDT) Received: from localhost ([::1]:55108 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oJFog-00049p-B4 for importer@patchew.org; Wed, 03 Aug 2022 10:57:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55232) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oJEe4-0005Zf-1j for qemu-devel@nongnu.org; Wed, 03 Aug 2022 09:42:44 -0400 Received: from smtp-fw-9103.amazon.com ([207.171.188.200]:48467) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oJEdz-000489-Nk for qemu-devel@nongnu.org; Wed, 03 Aug 2022 09:42:43 -0400 Received: from pdx4-co-svc-p1-lb2-vlan3.amazon.com (HELO email-inbound-relay-iad-1e-7dac3c4d.us-east-1.amazon.com) ([10.25.36.214]) by smtp-border-fw-9103.sea19.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Aug 2022 13:42:23 +0000 Received: from EX13D37EUA003.ant.amazon.com (iad12-ws-svc-p26-lb9-vlan3.iad.amazon.com [10.40.163.38]) by email-inbound-relay-iad-1e-7dac3c4d.us-east-1.amazon.com (Postfix) with ESMTPS id D5AD88C76A; Wed, 3 Aug 2022 13:42:21 +0000 (UTC) Received: from f4d4887fdcfb.ant.amazon.com (10.43.162.227) by EX13D37EUA003.ant.amazon.com (10.43.165.7) with Microsoft SMTP Server (TLS) id 15.0.1497.36; Wed, 3 Aug 2022 13:42:17 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.es; i=@amazon.es; q=dns/txt; s=amazon201209; t=1659534159; x=1691070159; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=x98uMoxWp5rgjNFDMbf+krw72BDczBR2Qf1VC9TcJC0=; b=dh21CGFYdROLBVCDprUccHZx383g+3iGr1bI8HToLHY+xEwsiJFibJzv ND116/MeKEgyRCcnAFTtwmlxbumzNct18KN6bC2Lx51QkeQ4gdaoFiqvl 3adrm9bcgVBLoWQaLwHcezRVuBIBtkPOHJoJi/TASfgAbTeva1/AYJFhL 4=; X-IronPort-AV: E=Sophos;i="5.93,214,1654560000"; d="scan'208";a="1040527117" From: To: CC: , , , , , , Subject: [PATCH 2/2] vmgenid: add generation counter Date: Wed, 3 Aug 2022 15:41:47 +0200 Message-ID: <20220803134147.31073-3-bchalios@amazon.es> X-Mailer: git-send-email 2.32.1 (Apple Git-133) In-Reply-To: <20220803134147.31073-1-bchalios@amazon.es> References: <20220803134147.31073-1-bchalios@amazon.es> MIME-Version: 1.0 X-Originating-IP: [10.43.162.227] X-ClientProxiedBy: EX13D41UWC002.ant.amazon.com (10.43.162.127) To EX13D37EUA003.ant.amazon.com (10.43.165.7) Precedence: Bulk Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=207.171.188.200; envelope-from=prvs=207aa399e=bchalios@amazon.es; helo=smtp-fw-9103.amazon.com X-Spam_score_int: -44 X-Spam_score: -4.5 X-Spam_bar: ---- X-Spam_report: (-4.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.082, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Wed, 03 Aug 2022 10:54:38 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @amazon.es) X-ZM-MESSAGEID: 1659538667826100001 Content-Type: text/plain; charset="utf-8" From: Babis Chalios Some user-space applications such as user-space PRNGs or applications that keep world-unique data need to be notified about VM restore events, so that they modify their internal state. However, the vmgenid 128-bits UUID is consumed by the guest kernel to reseed its RNG, hence it is not suitable to be exposed to user-space. In order to address the user-space needs this commit extends the vmgenid to include a 32-bits generation counter. The value of the counter is meant to be increased every time we start a new VM from a saved state. It is stored in a page aligned, one page-long buffer, so that it allows the guest kernel to expose it as an mmap-able device to the user-space for low latency access, out of the notification path. Signed-off-by: Babis Chalios --- docs/specs/vmgenid.txt | 97 +++++++++++++++++++++++++++------------ hw/acpi/vmgenid.c | 96 +++++++++++++++++++++++++++----------- include/hw/acpi/vmgenid.h | 9 +++- 3 files changed, 144 insertions(+), 58 deletions(-) diff --git a/docs/specs/vmgenid.txt b/docs/specs/vmgenid.txt index 5274b4c895..3cf6d0e191 100644 --- a/docs/specs/vmgenid.txt +++ b/docs/specs/vmgenid.txt @@ -20,6 +20,15 @@ guest operating system notices the change, and is then a= ble to react as appropriate by marking its copies of distributed databases as dirty, re-initializing its random number generator etc. =20 +Currently, in Linux the UUID exposed by vmgenid is consumed by the guest k= ernel +to reseed its RNG and not exposed in the user-space, hence leaving applica= tions +without a mechanism which would help them detect a VM restore event. + +To address the use-case of user-space applications we extend the vmgenid +specification to include a 32-bit generation counter. The counter needs to= be +incremented every time a VM is loaded from a saved state by the user. The = guest +kernel needs to expose to user-space applications which should monitor it = for +detecting the VM-load event. =20 Requirements ------------ @@ -53,12 +62,24 @@ R2 to R5. [These AML requirements are isolated well eno= ugh in the Microsoft R6. The hypervisor shall expose a _HID (hardware identifier) object in the VMGenId device's scope that is unique to the hypervisor vendor. =20 +The generation counter and the buffer holding it shall adhere to the same +requirements as the generation ID. Moreover, + +R7. The BIOS will need to include an object below the device named "CTRA", + which, similarly to "ADDR", will evaluate to a package of two integers= . The + first integer must be the low 32-bits of the guest physical address of= the + buffer that contains generation counter. The second integer must be the + hight 32 bits of the guest physical address of the same buffer. + +R8. The buffer holding the generation counter will be page aligned and 1 p= age + long. + =20 QEMU Implementation ------------------- =20 The above-mentioned specification does not dictate which ACPI descriptor t= able -will contain the VM Generation ID device. Other implementations (Hyper-V = and +will contain the VM Generation ID device. Other implementations (Hyper-V a= nd Xen) put it in the main descriptor table (Differentiated System Description Table or DSDT). For ease of debugging and implementation, we have decided= to put it in its own Secondary System Description Table, or SSDT. @@ -72,8 +93,8 @@ ASL+ Optimizing Compiler version 20150717-64 Copyright (c) 2000 - 2015 Intel Corporation =20 Reading ACPI table from file /sys/firmware/acpi/tables/SSDT - Length -00000198 (0x0000C6) -ACPI: SSDT 0x0000000000000000 0000C6 (v01 BOCHS VMGENID 00000001 BXPC +00000236 (0x0000EC) +ACPI: SSDT 0x0000000000000000 0000EC (v01 BOCHS VMGENID 00000001 BXPC 00000001) Acpi table [SSDT] successfully installed and loaded Pass 1 parse of [SSDT] @@ -95,9 +116,9 @@ ASL Output: ./SSDT.dsl - 1631 bytes * * Original Table Header: * Signature "SSDT" - * Length 0x000000CA (202) + * Length 0x000000EC (236) * Revision 0x01 - * Checksum 0x4B + * Checksum 0x63 * OEM ID "BOCHS " * OEM Table ID "VMGENID" * OEM Revision 0x00000001 (1) @@ -133,6 +154,14 @@ DefinitionBlock ("/sys/firmware/acpi/tables/SSDT.aml",= "SSDT", 1, "BOCHS ", Index (Local0, One) =3D Zero Return (Local0) } + + Method (CTRA, 0, NotSerialized) + { + Local0 =3D Package (0x02) {} + Local0 [Zero] =3D (VGIA + 0x1000) + Local0 [One] =3D Zero + Return (Local0) + } } } =20 @@ -161,7 +190,8 @@ More information about fw_cfg can be found in "docs/spe= cs/fw_cfg.txt" =20 Two fw_cfg blobs are used in this case: =20 -/etc/vmgenid_guid - contains the actual VM Generation ID GUID +/etc/vmgenid_data - contains the actual VM Generation ID GUID and Generati= on + counter - read-only to the guest /etc/vmgenid_addr - contains the address of the downloaded vmgenid blob - writable by the guest @@ -169,14 +199,14 @@ Two fw_cfg blobs are used in this case: =20 QEMU sends the following commands to the guest at startup: =20 -1. Allocate memory for vmgenid_guid fw_cfg blob. -2. Write the address of vmgenid_guid into the SSDT (VGIA ACPI variable as +1. Allocate memory for vmgenid_data fw_cfg blob. +2. Write the address of vmgenid_data into the SSDT (VGIA ACPI variable as shown above in the iasl dump). Note that this change is not propagated back to QEMU. -3. Write the address of vmgenid_guid back to QEMU's copy of vmgenid_addr +3. Write the address of vmgenid_data back to QEMU's copy of vmgenid_addr via the fw_cfg DMA interface. =20 -After step 3, QEMU is able to update the contents of vmgenid_guid at will. +After step 3, QEMU is able to update the contents of vmgenid_data at will. =20 Since BIOS or UEFI does not necessarily run when we wish to change the GUI= D, the value of VGIA is persisted via the VMState mechanism. @@ -196,46 +226,53 @@ All GUID passed in via command line or monitor are tr= eated as big-endian. GUID values displayed via monitor are shown in big-endian format. =20 =20 -GUID Storage Format: +vmgenid Storage Format: -------------------- =20 -In order to implement an OVMF "SDT Header Probe Suppressor", the contents = of -the vmgenid_guid fw_cfg blob are not simply a 128-bit GUID. There is also -significant padding in order to align and fill a memory page, as shown in = the -following diagram: +The contents of the vmgenid_data fw_cfg blob are two memory pages. In begi= nning +of the first page lives the OVMF SDT Header probe padded so that GUID is s= tored +in an 8-byte aligned address. Immediately after that is stored the GUID +followed by padding until the end of the page. The genration counter lives +in the beginning of the second page. The rest of the page is padded with z= eros. +The layout is shown in the following diagram: =20 +----------------------------------+ | SSDT with OEM Table ID =3D VMGENID | +----------------------------------+ | ... | TOP OF PAGE -| VGIA dword object ---------------|-----> +---------------------------+ -| ... | | fw-allocated array for | -| _STA method referring to VGIA | | "etc/vmgenid_guid" | -| ... | +---------------------------+ -| ADDR method referring to VGIA | | 0: OVMF SDT Header probe | -| ... | | suppressor | -+----------------------------------+ | 36: padding for 8-byte | - | alignment | - | 40: GUID | - | 56: padding to page size | - +---------------------------+ - END OF PAGE +| VGIA dword object ---------------|-----> +------------------------------= ------+ +| ... | | fw-allocated array for = | +| _STA method referring to VGIA | | "etc/vmgenid_data" = | +| ... | +------------------------------= ------+ +| ADDR method referring to VGIA | | 0: OVMF SDT Header probe = | +| ... | | suppressor = | ++----------------------------------+ | 36: padding for 8-byte = | + | alignment = | + | 40: GUID = | + | 56: padding to page size = | + | = | + | ... = | + | PAGE_SIZE : Gen counter = | + | PAGE_SIZE + 4: padding to pag= e size| + +------------------------------= ------+ =20 =20 Device Usage: ------------- =20 -The device has two properties, which may be only be set using the command = line: +The device has three properties, which may be only be set using the command +line: =20 guid - sets the value of the GUID. A special value "auto" instructs QEMU to generate a new random GUID. page-size - sets the target machines page size. Currently accepted values are 4096 (default) and 65536. + genctr - sets the Generation counter of the VM. =20 For example: =20 - QEMU -device vmgenid,guid=3D"324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87",page= -size=3D65536 - QEMU -device vmgenid,guid=3Dauto + QEMU -device vmgenid,guid=3D"324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87",page= -size=3D65536,genctr=3D0 + QEMU -device vmgenid,guid=3Dauto,genctr=3D42 =20 The property may be queried via QMP/HMP: =20 diff --git a/hw/acpi/vmgenid.c b/hw/acpi/vmgenid.c index ac2b116b6a..980d19daf3 100644 --- a/hw/acpi/vmgenid.c +++ b/hw/acpi/vmgenid.c @@ -24,7 +24,7 @@ #include "migration/vmstate.h" #include "sysemu/reset.h" =20 -void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_data, GArray *gui= d, +void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_data, GArray *vmg= enid, BIOSLinker *linker, const char *oem_id) { Aml *ssdt, *dev, *scope, *method, *addr, *if_ctx; @@ -34,17 +34,26 @@ void vmgenid_build_acpi(VmGenIdState *vms, GArray *tabl= e_data, GArray *guid, .oem_id =3D oem_id, .oem_table_id =3D "VMGENID" }; =20 /* Fill in the GUID values. These need to be converted to little-endi= an - * first, since that's what the guest expects + * first, since that's what the guest expects. Allocate two pages, so = that + * we can dedicate a full page (the second one) to the generation coun= ter. */ - g_array_set_size(guid, vms->page_size - ARRAY_SIZE(guid_le.data)); + g_array_set_size(vmgenid, 2 * vms->page_size - ARRAY_SIZE(guid_le.data) + - sizeof(vms->gen_ctr)); guid_le =3D qemu_uuid_bswap(vms->guid); /* The GUID is written at a fixed offset into the fw_cfg file * in order to implement the "OVMF SDT Header probe suppressor" * see docs/specs/vmgenid.txt for more details */ - g_array_insert_vals(guid, VMGENID_GUID_OFFSET, guid_le.data, + g_array_insert_vals(vmgenid, VMGENID_GUID_OFFSET, guid_le.data, ARRAY_SIZE(guid_le.data)); =20 + /* Write the generation counter at the beginning of the second page of + * the fw_cfg file. + */ + g_array_insert_vals(vmgenid, vms->page_size, (uint8_t *)&vms->gen_ctr, + sizeof(vms->gen_ctr)); + vms->has_gen_ctr =3D true; + /* Put VMGNEID into a separate SSDT table */ acpi_table_begin(&table, table_data); ssdt =3D init_aml_allocator(); @@ -84,6 +93,23 @@ void vmgenid_build_acpi(VmGenIdState *vms, GArray *table= _data, GArray *guid, aml_append(method, aml_return(addr)); =20 aml_append(dev, method); + + /* the CTRA method returns two 32-bit words representing the lower and + * upper halves of the physical address of the Generation counter insi= de + * the fw_cfg blob + */ + method =3D aml_method("CTRA", 0, AML_NOTSERIALIZED); + + addr =3D aml_local(0); + aml_append(method, aml_store(aml_package(2), addr)); + aml_append(method, aml_store(aml_add(aml_name("VGIA"), + aml_int(vms->page_size), NULL), + aml_index(addr, aml_int(0)))); + aml_append(method, aml_store(aml_int(0), aml_index(addr, aml_int(1)))); + aml_append(method, aml_return(addr)); + + aml_append(dev, method); + aml_append(scope, dev); aml_append(ssdt, scope); =20 @@ -95,8 +121,8 @@ void vmgenid_build_acpi(VmGenIdState *vms, GArray *table= _data, GArray *guid, g_array_append_vals(table_data, ssdt->buf->data, ssdt->buf->len); =20 /* Allocate guest memory for the Data fw_cfg blob */ - bios_linker_loader_alloc(linker, VMGENID_GUID_FW_CFG_FILE, guid, - vms->page_size, + bios_linker_loader_alloc(linker, VMGENID_DATA_FW_CFG_FILE, vmgenid, + 2 * vms->page_size, false /* page boundary, high memory */); =20 /* Patch address of GUID fw_cfg blob into the ADDR fw_cfg blob @@ -108,7 +134,7 @@ void vmgenid_build_acpi(VmGenIdState *vms, GArray *tabl= e_data, GArray *guid, */ bios_linker_loader_write_pointer(linker, VMGENID_ADDR_FW_CFG_FILE, 0, sizeof(uint64_t), - VMGENID_GUID_FW_CFG_FILE, VMGENID_GUID_OFFSET); + VMGENID_DATA_FW_CFG_FILE, VMGENID_GUID_OFFSET); =20 /* Patch address of GUID fw_cfg blob into the AML so OSPM can retrieve * and read it. Note that while we provide storage for 64 bits, only @@ -116,17 +142,18 @@ void vmgenid_build_acpi(VmGenIdState *vms, GArray *ta= ble_data, GArray *guid, */ bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE, vgia_offset, sizeof(uint32_t), - VMGENID_GUID_FW_CFG_FILE, 0); + VMGENID_DATA_FW_CFG_FILE, 0); =20 /* must be called after above command to ensure correct table checksum= */ acpi_table_end(linker, &table); free_aml_allocator(); } =20 -void vmgenid_add_fw_cfg(VmGenIdState *vms, FWCfgState *s, GArray *guid) +void vmgenid_add_fw_cfg(VmGenIdState *vms, FWCfgState *s, GArray *vmgenid) { - /* Create a read-only fw_cfg file for GUID */ - fw_cfg_add_file(s, VMGENID_GUID_FW_CFG_FILE, guid->data, vms->page_siz= e); + /* Create a read-only fw_cfg file for vmgenid data */ + fw_cfg_add_file(s, VMGENID_DATA_FW_CFG_FILE, vmgenid->data, + 2 * vms->page_size); /* Create a read-write fw_cfg file for Address */ fw_cfg_add_file_callback(s, VMGENID_ADDR_FW_CFG_FILE, NULL, NULL, NULL, vms->vmgenid_addr_le, @@ -136,7 +163,7 @@ void vmgenid_add_fw_cfg(VmGenIdState *vms, FWCfgState *= s, GArray *guid) static void vmgenid_update_guest(VmGenIdState *vms) { Object *obj =3D object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, NULL= ); - uint32_t vmgenid_addr; + uint32_t vmgenid_addr, vmgenid_gen_ctr_addr; QemuUUID guid_le; =20 if (obj) { @@ -146,22 +173,36 @@ static void vmgenid_update_guest(VmGenIdState *vms) /* A zero value in vmgenid_addr means that BIOS has not yet written * the address */ - if (vmgenid_addr) { - /* QemuUUID has the first three words as big-endian, and expect - * that any GUIDs passed in will always be BE. The guest, - * however, will expect the fields to be little-endian. - * Perform a byte swap immediately before writing. - */ - guid_le =3D qemu_uuid_bswap(vms->guid); - /* The GUID is written at a fixed offset into the fw_cfg file - * in order to implement the "OVMF SDT Header probe suppressor" - * see docs/specs/vmgenid.txt for more details. - */ - cpu_physical_memory_write(vmgenid_addr, guid_le.data, - sizeof(guid_le.data)); - /* Send _GPE.E05 event */ - acpi_send_event(DEVICE(obj), ACPI_VMGENID_CHANGE_STATUS); + if (!vmgenid_addr) { + return; + } + + /* Only update the generation counter if the original guest suppor= ted + * it. + */ + if (vms->has_gen_ctr) { + /* The generation counter address is in the second page of the= blob */ + vmgenid_gen_ctr_addr =3D vmgenid_addr - VMGENID_GUID_OFFSET + + vms->page_size; + + cpu_physical_memory_write(vmgenid_gen_ctr_addr, &vms->gen_ctr, + sizeof(vms->gen_ctr)); } + + /* QemuUUID has the first three words as big-endian, and expect + * that any GUIDs passed in will always be BE. The guest, + * however, will expect the fields to be little-endian. + * Perform a byte swap immediately before writing. + */ + guid_le =3D qemu_uuid_bswap(vms->guid); + /* The GUID is written at a fixed offset into the fw_cfg file + * in order to implement the "OVMF SDT Header probe suppressor" + * see docs/specs/vmgenid.txt for more details. + */ + cpu_physical_memory_write(vmgenid_addr, guid_le.data, + sizeof(guid_le.data)); + /* Send _GPE.E05 event */ + acpi_send_event(DEVICE(obj), ACPI_VMGENID_CHANGE_STATUS); } } =20 @@ -266,6 +307,7 @@ static Property vmgenid_device_properties[] =3D { DEFINE_PROP_UUID(VMGENID_GUID, VmGenIdState, guid), DEFINE_PROP_UNSIGNED(VMGENID_PAGE_SIZE, VmGenIdState, page_size, 0, vmgenid_prop_page_size, uint32_t), + DEFINE_PROP_UINT32(VMGENID_GEN_CTR, VmGenIdState, gen_ctr, 0), DEFINE_PROP_END_OF_LIST(), }; =20 diff --git a/include/hw/acpi/vmgenid.h b/include/hw/acpi/vmgenid.h index e4d83f5c74..56dd7533b0 100644 --- a/include/hw/acpi/vmgenid.h +++ b/include/hw/acpi/vmgenid.h @@ -9,7 +9,8 @@ #define TYPE_VMGENID "vmgenid" #define VMGENID_GUID "guid" #define VMGENID_PAGE_SIZE "page-size" -#define VMGENID_GUID_FW_CFG_FILE "etc/vmgenid_guid" +#define VMGENID_GEN_CTR "genctr" +#define VMGENID_DATA_FW_CFG_FILE "etc/vmgenid_data" #define VMGENID_ADDR_FW_CFG_FILE "etc/vmgenid_addr" =20 #define VMGENID_DEFAULT_FW_PAGE_SIZE 4096 /* Assume 4K page by default */ @@ -22,6 +23,12 @@ OBJECT_DECLARE_SIMPLE_TYPE(VmGenIdState, VMGENID) struct VmGenIdState { DeviceState parent_obj; QemuUUID guid; /* The 128-bit GUID seen by the guest */ + uint32_t gen_ctr; /* A 32bit generation counter meant to + * be exposed in the guest user-space + */ + bool has_gen_ctr; /* Backwards compatibility: Only update a + * guest when generation current present + */ uint8_t vmgenid_addr_le[8]; /* Address of the GUID (little-endian) */ uint32_t page_size; /* Page size to use as a the allocation = unit */ }; --=20 2.32.1 (Apple Git-133) Amazon Spain Services sociedad limitada unipersonal, Calle Ramirez de Prado= 5, 28045 Madrid. Registro Mercantil de Madrid . Tomo 22458 . Folio 102 . H= oja M-401234 . CIF B84570936