From nobody Sun Sep 28 16:28:08 2025 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=1758378724; cv=none; d=zohomail.com; s=zohoarc; b=Xr6pA6FL6+ozP7pWbGsGvFQlsO0hksen6O0ZuaoMY6M2gRMBSNnWlwURBSI8zLFqmxFwnCJteul2d75SMaVKihyvyLXJcfO/MziZE87zAW6KAYUisOJar+Z1TO2pVe9Yhkjlh9Kh0Vy2WWhHeIIs+Op+vWIRNF6rwtwaKexCeew= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1758378724; 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=fJ3YNFEPq2/8msLkXx1NZ4U+hOxlX3VeLMqMSz14QdI=; b=nbczcNLeN1JteC/ybU1uNUFvnv6+VoV8k0oDT9ehukL5nKH/eaNvCFuyajeZ0tFxyZzgjwyhhZTmJ+i9gOCm0wexA3cyfbP7MS2nt2CAUsPhzyhNq0Zv3ED97wA4tX9h/eSuAFq2lfpfdeeDodqqtyRtkD8DZS5q3o0cIkyBdOs= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758378724766653.3740829027145; Sat, 20 Sep 2025 07:32:04 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uzybL-0007FA-7e; Sat, 20 Sep 2025 10:30:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uzybJ-0007EQ-Ai for qemu-devel@nongnu.org; Sat, 20 Sep 2025 10:30:09 -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 1uzybH-0005QQ-Mh for qemu-devel@nongnu.org; Sat, 20 Sep 2025 10:30:08 -0400 Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-390-6LkvF3GKM5-Tt21ys0aBRQ-1; Sat, 20 Sep 2025 10:30:05 -0400 Received: by mail-wm1-f72.google.com with SMTP id 5b1f17b1804b1-45de07b831dso17774155e9.1 for ; Sat, 20 Sep 2025 07:30:05 -0700 (PDT) Received: from [192.168.10.48] ([151.95.47.123]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-45f32136cdasm99628655e9.4.2025.09.20.07.30.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 20 Sep 2025 07:30:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1758378607; 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=fJ3YNFEPq2/8msLkXx1NZ4U+hOxlX3VeLMqMSz14QdI=; b=hgQ2X7ixbrM4qSSXK571LmVtoSA9TbmsBui39p7XhiypQTlnERm4T3UEgLj9UjpJAAhXdl IiE5JhXEXwSmRXweK/HwuU9wuEfLZF7mZoi1NJs7TP9r5brGqnsCk5Vr0+Il+5YmiJMors 8LlLPtQwxc69ulJ6DEJ1VM8BdPNM2nU= X-MC-Unique: 6LkvF3GKM5-Tt21ys0aBRQ-1 X-Mimecast-MFC-AGG-ID: 6LkvF3GKM5-Tt21ys0aBRQ_1758378604 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758378603; x=1758983403; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=fJ3YNFEPq2/8msLkXx1NZ4U+hOxlX3VeLMqMSz14QdI=; b=Ucz4W5XOUqFDYpgSnOJLdkG4xzuwABYwTPlvj9BMyNpbZXV5hzOIsw+u9AQzGtPF2f HZgYucSnmChyU2v7WaTh/HB2bM7fZFiXGkZHtrmaxI8aLj8tw/5TsBAL/+GkH78n47XH Jw+OtK9gYq+ns8g5SGb1b18zeYVE/q0LePEJJd9bTPQ/lqd9bFyMVrXKKx49jfSdq8GJ EDdQBrwZpTyeyqwqIFd3W5fx24Uy85XaCV1LH3ejvbASltZs/m6K6Q4GT2mi748vch6d XxAyoIZLbTUXh2evGdNXKq1XXwZ/XJstzrFD/8KMEWSV77pERHtsMMRYkV4SR1I3OjoT M3AA== X-Gm-Message-State: AOJu0YwZ5WdXiPs3PQpWQLYOS84/gFT2/4vQ2tPDhE/k44FEi7Qd+tO4 YWsLkDX2VIQvS+/SA8Jq7gUNeZR92hzRG0B3MgulgRc5cxapsDr30OXhN8Oe+MnROacwww3e1+K ZKPEMPc47w/k1qfLfRUIxJtb+EgsuPJtbh5/+0/CiTUopevvatESb4GYNzMsyTFVHFcNEEKNJwO kHK16VadPVIUcVdbke0Gsr7mwBPLpnHxIHmZeHaNvB X-Gm-Gg: ASbGncvRQP9rYb9VHuCNmJcuaVMVA3M1BJjGzPnmoUYGwerCwp+TgTVQhTP5PC9dF6u W3GAN8KXjC6ZDWWj1lvBAc5WX1ds936aj8BGIIRAZzlM792yJ2eGpEuBkR+5hESc5gnf9yTl+dB xypoHdS6LmiJbMgoftF53eVH3MPGAthHMaYqXJT0xiCbJKAYVkb5oG+OW78+bR1+GiK2iPsWIsl UnEPYY81TfuYs6m0Cr3jYbRiLBYt29MDRLZY6DLjU2Pg5pd5qRvU9XrdBycmKaqaKY63PftwaP5 eta8hF9wQ1oEr2KoB2fLDHWF/4arVBRk0KNYJCNCCryy2SyELWhPIuYHJAxAok1m5fx4xNyyQHX AVNUak84lgkzC3mhZUnwTjvvEhJ7u8Xo3V3GSF8SP2KU= X-Received: by 2002:a05:600c:1d91:b0:468:11af:782b with SMTP id 5b1f17b1804b1-46811af793emr56247815e9.29.1758378603311; Sat, 20 Sep 2025 07:30:03 -0700 (PDT) X-Google-Smtp-Source: AGHT+IH/qk76o0RmehkijCLaE4imfHrVhxw+6WVQ5uZMGzREY2hhrdZoKipoZrfdr7YlRVt3B9wLmA== X-Received: by 2002:a05:600c:1d91:b0:468:11af:782b with SMTP id 5b1f17b1804b1-46811af793emr56247585e9.29.1758378602834; Sat, 20 Sep 2025 07:30:02 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, zhao1.liu@intel.com, manos.pitsidianakis@linaro.org Subject: [PATCH 1/7] rust: bql: add BqlRefCell::get_mut() Date: Sat, 20 Sep 2025 16:29:52 +0200 Message-ID: <20250920142958.181910-2-pbonzini@redhat.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20250920142958.181910-1-pbonzini@redhat.com> References: <20250920142958.181910-1-pbonzini@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.045, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list 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-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1758378725467116600 Content-Type: text/plain; charset="utf-8" This method is rarely useful in QEMU due to the pervasiveness of shared references, but add it for when a &mut BqlRefCell<> is used. Signed-off-by: Paolo Bonzini --- rust/bql/src/cell.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/rust/bql/src/cell.rs b/rust/bql/src/cell.rs index 24ab294b60d..8a0c8c14ad4 100644 --- a/rust/bql/src/cell.rs +++ b/rust/bql/src/cell.rs @@ -580,6 +580,25 @@ pub fn borrow_mut(&self) -> BqlRefMut<'_, T> { } } =20 + /// Returns a mutable reference to the underlying data in this cell, + /// while the owner already has a mutable reference to the cell. + /// + /// # Examples + /// + /// ``` + /// use bql::BqlRefCell; + /// + /// let mut c =3D BqlRefCell::new(5); + /// + /// *c.get_mut() =3D 10; + /// ``` + #[inline] + pub const fn get_mut(&mut self) -> &mut T { + // SAFETY: there cannot be any outstanding borrow, + // since `self` is mutably owned. + unsafe { &mut *self.as_ptr() } + } + /// Returns a raw pointer to the underlying data in this cell. /// /// # Examples --=20 2.51.0 From nobody Sun Sep 28 16:28:08 2025 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=1758378661; cv=none; d=zohomail.com; s=zohoarc; b=eGieRuhKuvOYRUcaqAXK3OER3Z4lAcJ0Fw1CppDECXtB/VCk3Sncj8hMvyABoGzASbBvVrTdl/30f7yxsvdtZB647amQ9eNhjas3isyiw1z/4HVfEZ927l3sepDAZQXlwvznY80us3Pu0xxNlKJpFnJ2r0wKdbUH/mcD/jmGOM8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1758378661; 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=hD5c5Jjgf0+adbTjKcRhlLqzouuGQG7/y7gKp/DqW8w=; b=WbhDZ4+kJJ7Na3eh313Yphu4uHJ6ZweBQb8M+KnQfWyrd+WJ8oLM+bqK1vp0HOuPrBhoaz7ujczu0Guzi44ZBWlU5cNjiLeleNk9IdwiIfBDOHHB2fLQAGI4TLvxHV/iebE3oYFwyr7IUSqxF2abG8ZVvtWP4xBSbVUFkUX+xrI= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758378661056726.7264127660533; Sat, 20 Sep 2025 07:31:01 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uzybN-0007Gq-PN; Sat, 20 Sep 2025 10:30:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uzybM-0007GR-Fy for qemu-devel@nongnu.org; Sat, 20 Sep 2025 10:30:12 -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 1uzybK-0005Ri-O9 for qemu-devel@nongnu.org; Sat, 20 Sep 2025 10:30:12 -0400 Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-589--fAR6aSJM3SsLPLmCkbukQ-1; Sat, 20 Sep 2025 10:30:08 -0400 Received: by mail-wr1-f69.google.com with SMTP id ffacd0b85a97d-3ecdd61b798so1590190f8f.1 for ; Sat, 20 Sep 2025 07:30:07 -0700 (PDT) Received: from [192.168.10.48] ([151.95.47.123]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3ee0fbc7478sm12161228f8f.38.2025.09.20.07.30.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 20 Sep 2025 07:30:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1758378609; 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=hD5c5Jjgf0+adbTjKcRhlLqzouuGQG7/y7gKp/DqW8w=; b=D0VG1UpRmXkmtKiXuYBDx3+S3RogdD7J+DWuXzASNyPAMP9i9Pj3D6x0WUrDiB2PLuWoME qoP/hLomj0PGzpDowvZ+husM1fdTenGHmp6qBgF3HWi3fSzk3XzPaWvlxRNJhAZ9Cve1FG XiLJ0uEJ1tsm0RMYcW8McnaNjsxYuZc= X-MC-Unique: -fAR6aSJM3SsLPLmCkbukQ-1 X-Mimecast-MFC-AGG-ID: -fAR6aSJM3SsLPLmCkbukQ_1758378607 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758378606; x=1758983406; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=hD5c5Jjgf0+adbTjKcRhlLqzouuGQG7/y7gKp/DqW8w=; b=COgxUC6LjxAd+zZL8YcqchKnVODowHzuC7SuDspJXqe37701gtk7sURXMBD6lB2q4D 5GRYMsFQwOuUt4gZhYCNaSABlStI6et30DCP/5OtAGInn+2nc0vySkfz6hpqGYixxg1y oq6mpQaolGVh14mxdYzW5B9W4z/c8teRdrXtidw+F8027ZEiyWzJD5tohey1pgIuWh57 zsjOKfScVUEYED6lBa2nHCUskwMjwyZF7VDE9RKwAjqb/QMvR3mJa20IpueUtCQL8I3W WBDIBZDXxZm2FzCKhq5dY0BtdrMKDPhPhX2qp2H0RI+2ugj2zTzgQe/0BYW6tNl1UTOA XmOg== X-Gm-Message-State: AOJu0YwXr/+ypBY9nl9X8BEI9VGWaZszpCLuQWTbsqcn76bL5b+6avnA GaVZkOY4/rC0hE0ULxwk3my11TyETJEiYC+rB2xDXnF6jRyVxF/onVpgN3dCAQmd+X3gxteZl8i /0NPcmLe3bue/L7w55aKKwDKSeyEm3Sk8kJOKuTncC4su7DXiA5NB+4O8G8TSPKc1QM++jTrx/q lY6j9wCf9Xjz2i9FjikrecfebRNlI+65i5PiK7vtKX X-Gm-Gg: ASbGncuAsbejqUuWXh8ssdhoWT5HvSv7wxD6O6L+S6UqcuAQrRBQXhtELcHr16ggoE4 KUHlt2prQax/kNIM/bl2oCJQGHINv00ZB3ifvGqzqXS7oPsw3nHn1asADonvxDofPOfNoCjUqEw EK58HV1TLW3gQuwY8AHwARn5bi6zGeZLm7cJMGrFlQn8TrsP54WY6qPa7muwvsHI4XGGRH9CllT wMy4OA1xh/VDelv0b+5EZqYmL5dN7XWtnEoKGrw7bkYMOeOPpFiewioth4p7nFH+TDLxHmU4K2q +RfbOjWN5T/9R2Htai0Zq+vdeg8fk979WD7Ltm8YXC6/ejSBqm/DehxXAnfYctXHQcxLbDP/3wE XVkWc4D705ihnrUlUsGkcOozE7WDKN2P0Nht71CLjaNM= X-Received: by 2002:a05:6000:144f:b0:3ea:e0fd:290a with SMTP id ffacd0b85a97d-3ee7ca198bcmr5626470f8f.12.1758378605818; Sat, 20 Sep 2025 07:30:05 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEY2uIvO2v6ndyjsXpxAwwKXgH8Vk5vjX+Z7eR7PXHaulZbV6aLztuwVb3IsPXrIt3KaIJ9CA== X-Received: by 2002:a05:6000:144f:b0:3ea:e0fd:290a with SMTP id ffacd0b85a97d-3ee7ca198bcmr5626454f8f.12.1758378605369; Sat, 20 Sep 2025 07:30:05 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, zhao1.liu@intel.com, manos.pitsidianakis@linaro.org Subject: [PATCH 2/7] rust: move VMState from bql to migration Date: Sat, 20 Sep 2025 16:29:53 +0200 Message-ID: <20250920142958.181910-3-pbonzini@redhat.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20250920142958.181910-1-pbonzini@redhat.com> References: <20250920142958.181910-1-pbonzini@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.045, 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_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_FILL_THIS_FORM_SHORT=0.01 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list 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-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1758378663100116600 Content-Type: text/plain; charset="utf-8" The high-level wrapper Migratable will contain a BqlCell, which would introduce a circular dependency betwen the bql and migration crates. Move the implementation of VMState for cells to "migration", together with the implementation for std types. Signed-off-by: Paolo Bonzini Reviewed-by: Zhao Liu --- rust/Cargo.lock | 4 +--- rust/bql/Cargo.toml | 3 --- rust/bql/meson.build | 1 - rust/bql/src/cell.rs | 6 ------ rust/meson.build | 2 +- rust/migration/Cargo.toml | 1 + rust/migration/meson.build | 4 ++-- rust/migration/src/vmstate.rs | 2 ++ 8 files changed, 7 insertions(+), 16 deletions(-) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 2826c4d027b..960f603cedb 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -57,9 +57,6 @@ dependencies =3D [ [[package]] name =3D "bql" version =3D "0.1.0" -dependencies =3D [ - "migration", -] =20 [[package]] name =3D "chardev" @@ -141,6 +138,7 @@ checksum =3D "18d287de67fe55fd7e1581fe933d965a5a9477b38= e949cfa9f8574ef01506398" name =3D "migration" version =3D "0.1.0" dependencies =3D [ + "bql", "common", "util", ] diff --git a/rust/bql/Cargo.toml b/rust/bql/Cargo.toml index 1041bd4ea93..d87edf4c302 100644 --- a/rust/bql/Cargo.toml +++ b/rust/bql/Cargo.toml @@ -12,9 +12,6 @@ license.workspace =3D true repository.workspace =3D true rust-version.workspace =3D true =20 -[dependencies] -migration =3D { path =3D "../migration" } - [features] default =3D ["debug_cell"] debug_cell =3D [] diff --git a/rust/bql/meson.build b/rust/bql/meson.build index 7214d944089..305d7111897 100644 --- a/rust/bql/meson.build +++ b/rust/bql/meson.build @@ -36,7 +36,6 @@ _bql_rs =3D static_library( override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_abi: 'rust', rust_args: _bql_cfg, - link_with: [_migration_rs], ) =20 bql_rs =3D declare_dependency(link_with: [_bql_rs], diff --git a/rust/bql/src/cell.rs b/rust/bql/src/cell.rs index 8a0c8c14ad4..defa45a3294 100644 --- a/rust/bql/src/cell.rs +++ b/rust/bql/src/cell.rs @@ -151,8 +151,6 @@ ptr::NonNull, }; =20 -use migration::impl_vmstate_transparent; - /// A mutable memory location that is protected by the Big QEMU Lock. /// /// # Memory layout @@ -364,8 +362,6 @@ pub fn take(&self) -> T { } } =20 -impl_vmstate_transparent!(crate::cell::BqlCell where T: VMState); - /// A mutable memory location with dynamically checked borrow rules, /// protected by the Big QEMU Lock. /// @@ -693,8 +689,6 @@ fn from(t: T) -> BqlRefCell { } } =20 -impl_vmstate_transparent!(crate::cell::BqlRefCell where T: VMState); - struct BorrowRef<'b> { borrow: &'b Cell, } diff --git a/rust/meson.build b/rust/meson.build index 0bb2a9630a1..f4fb7daf05a 100644 --- a/rust/meson.build +++ b/rust/meson.build @@ -29,8 +29,8 @@ subdir('qemu-macros') subdir('common') subdir('bits') subdir('util') -subdir('migration') subdir('bql') +subdir('migration') subdir('qom') subdir('system') subdir('chardev') diff --git a/rust/migration/Cargo.toml b/rust/migration/Cargo.toml index 708bfaaa682..f4a86275152 100644 --- a/rust/migration/Cargo.toml +++ b/rust/migration/Cargo.toml @@ -13,6 +13,7 @@ repository.workspace =3D true rust-version.workspace =3D true =20 [dependencies] +bql =3D { path =3D "../bql" } common =3D { path =3D "../common" } util =3D { path =3D "../util" } =20 diff --git a/rust/migration/meson.build b/rust/migration/meson.build index 2a49bd1633e..2f38da9220f 100644 --- a/rust/migration/meson.build +++ b/rust/migration/meson.build @@ -36,12 +36,12 @@ _migration_rs =3D static_library( ), override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_abi: 'rust', - link_with: [_util_rs], + link_with: [_util_rs, _bql_rs], dependencies: [common_rs], ) =20 migration_rs =3D declare_dependency(link_with: [_migration_rs], - dependencies: [migration, qemuutil]) + dependencies: [bql_rs, migration, qemuutil]) =20 # Doctests are essentially integration tests, so they need the same depend= encies. # Note that running them requires the object files for C code, so place th= em diff --git a/rust/migration/src/vmstate.rs b/rust/migration/src/vmstate.rs index e04b19b3c9f..05a833a8b7d 100644 --- a/rust/migration/src/vmstate.rs +++ b/rust/migration/src/vmstate.rs @@ -275,6 +275,8 @@ unsafe impl<$base> $crate::vmstate::VMState for $type w= here $base: $crate::vmsta }; } =20 +impl_vmstate_transparent!(bql::BqlCell where T: VMState); +impl_vmstate_transparent!(bql::BqlRefCell where T: VMState); impl_vmstate_transparent!(std::cell::Cell where T: VMState); impl_vmstate_transparent!(std::cell::UnsafeCell where T: VMState); impl_vmstate_transparent!(std::pin::Pin where T: VMState); --=20 2.51.0 From nobody Sun Sep 28 16:28:08 2025 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=1758378667; cv=none; d=zohomail.com; s=zohoarc; b=QGkw+5R8m+PjaldlMFhI1wI6kKWXV7iKMZi+F8/Jpt8t8rxAkAogRQ/U4+8bESyZyyVeMFaMwsYruEHtU4YSa1nVEWVyf4r8b/B5rriHf2hp1yEj77ZUO2OcZiNHE5pp7cVkAIzinN0YukBQRBw4pnuclE5LhgC6BfXkIwz5YMk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1758378667; 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=Y0J9X0otTLwkzasLt1UDH9KlN9sxJ9cBWuhH6pKrvTE=; b=g23okqTxSQHys6H19wgQNikqbVfDN6W0k7sOg2bm1a0Rn4AKtPN0mXKn8oVPxwPbXTBXiv2ge1uInkxr2tGxhEk6Xs481rdAP0Aolb67hd2yj8RyRdWZe7Q05kob6tdRl3O3iEmElFP3k6MgiPGtocRDckqkEP1J47srfugwZ1k= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758378667529777.7634675749638; Sat, 20 Sep 2025 07:31:07 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uzybQ-0007Hs-UU; Sat, 20 Sep 2025 10:30:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uzybO-0007Gw-97 for qemu-devel@nongnu.org; Sat, 20 Sep 2025 10:30: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 1uzybM-0005S6-Dj for qemu-devel@nongnu.org; Sat, 20 Sep 2025 10:30:14 -0400 Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-651-kmII5KM-NnOINQYjoSfDMg-1; Sat, 20 Sep 2025 10:30:10 -0400 Received: by mail-wm1-f69.google.com with SMTP id 5b1f17b1804b1-45f2b9b99f0so932725e9.1 for ; Sat, 20 Sep 2025 07:30:10 -0700 (PDT) Received: from [192.168.10.48] ([151.95.47.123]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4613e09f879sm166476175e9.19.2025.09.20.07.30.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 20 Sep 2025 07:30:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1758378611; 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=Y0J9X0otTLwkzasLt1UDH9KlN9sxJ9cBWuhH6pKrvTE=; b=NLlOFUX9QTS0pxVGp4oNTu8sOuVwOz+nNs+n8ZPr9aWj7Bl6HCAvFPC1Cf2BY4GReCrRWl W9UWpGS24dbPXFeQx6SNFwJaVLQ2lD+G47J9SwoVyulFMegwyqo+npmSCN+fNyLj6mftcz +A943hhvisxykBhdjXRVJ4ugB0n7sVA= X-MC-Unique: kmII5KM-NnOINQYjoSfDMg-1 X-Mimecast-MFC-AGG-ID: kmII5KM-NnOINQYjoSfDMg_1758378609 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758378608; x=1758983408; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Y0J9X0otTLwkzasLt1UDH9KlN9sxJ9cBWuhH6pKrvTE=; b=RD4KyRk6YEpf0NwxML9rjmuDuoPN65PdYIkUVLAdK7cxnnnF9KK1DexhMqprS3mURd 3H3B1PLm7WvJHnlLmeXC/uJ7WDKWnK9azdWjRHgakbD7srljUwonNPW6BlVZaBxUp5zn nepO+rqhavvxVghjAwNG8SzNAl52nXDdSuQeE6GqK8t1Z28T6dOc9Yw0BCEr2iHOidC8 fj+4BbytbalxkJtRd5reV8EsTnG4VohpV61N6JU7SQPVTKh1yDi5nqNdm2Kzm5KidZ39 5zMO3li0gbe+EWBIPbtTuXhRBLvCUr7oD6hhgYgOfeGvFZnLBuI5Cr05x1bFaTQxXjT8 1AVg== X-Gm-Message-State: AOJu0YyEJPO5KKNfGn4GB8Ufh9PLhsnVbfAArVjthvdyNgttaWB9ZD2M WA/3yuK3qH9l48oqGD8n2Qa6opCtDkXstWp07TKQNBfql9writPyPoLaY6YQ6AuobAlyBuzViQy /uY359CeUurlSh2/XL5mi+Xa/RXow2b8Q/IdXXI0Fk2vPkMD0eBXQuKyuQucOLOOs8oMgq7Hhx+ s3RmriaEMq1rOLq6LvxzW35r+7mVrCAJCVJgmHiBbB X-Gm-Gg: ASbGncuEvHXSnBCJgvneNiyRD08sAPKlabSI+azHOAbXOeWuRNpCyn9pplHuy7PBwPL L7TU/h05adCspWjll1YNGJVwG1Q+ip5YEdB5UhFrjlcbvt6LGPLo3GWcStT94LpLIG1sv1WDEcG R90m7tERYLmQhO4hguRTtX5+e/dJpuSnF3eum9Ugpv2tF1D1i8RbaPe2CflF/tmfgKiMqhOZWJ1 fcIaNpMvocMjJKrUvr8SL4la9aiLnV8jl+wS7dAoIncOzz5f4DUrAJr7iZYcFTs6vslu1rxERq9 Qtg/qGdcmvLdiwnF8c3XhbFJFajhW/4ZadTa6v1SIvP12uF0rk7sNe1jv9GcqGIOxpHU3NqNQYf beaW3rmeIoeLhXks7ytXJ+sm0jvHNSoEE0KVfF5U+KjI= X-Received: by 2002:a05:600c:34c8:b0:45b:8b95:7119 with SMTP id 5b1f17b1804b1-464f81642e8mr114252285e9.8.1758378608032; Sat, 20 Sep 2025 07:30:08 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGfhatReDU9ArBw+DDqbbFgu0vDxDVZRAp48hqeXuZBgwvm6fdJ6o4wpAJAY0O0Bz46Q6z3mQ== X-Received: by 2002:a05:600c:34c8:b0:45b:8b95:7119 with SMTP id 5b1f17b1804b1-464f81642e8mr114252005e9.8.1758378607504; Sat, 20 Sep 2025 07:30:07 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, zhao1.liu@intel.com, manos.pitsidianakis@linaro.org Subject: [PATCH 3/7] rust: migration: extract vmstate_fields_ref Date: Sat, 20 Sep 2025 16:29:54 +0200 Message-ID: <20250920142958.181910-4-pbonzini@redhat.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20250920142958.181910-1-pbonzini@redhat.com> References: <20250920142958.181910-1-pbonzini@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.045, 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_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list 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-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1758378668831116600 Content-Type: text/plain; charset="utf-8" This is useful when building a VMState for generic structs, because you have to avoid nested statics. Using vmstate_fields! will fail in the likely case where the _FIELDS static uses Self from an outer item, because that is forbidden. I also looked into returning a &'static [VMStateField] from vmstate_fields!, but that also fails; the fields are not promoted to static, which is unfortunate but intentional (https://github.com/rust-lang/rust/issues/60502= ): error[E0716]: temporary value dropped while borrowed --> rust/hw/char/pl011/libpl011.rlib.p/structured/device.rs:743:17 | 738 | / VMStateDescriptionBuilder::::new() 739 | | .name(c"pl011/clock") 740 | | .version_id(1) 741 | | .minimum_version_id(1) 742 | | .needed(&PL011State::clock_needed) 743 | | .fields(vmstate_fields! { | | _________________^ 744 | || vmstate_of!(PL011State, clock), 745 | || }) | ||_________^- argument requires that borrow lasts for `'static` | |_________| | creates a temporary value which is freed while still in use 746 | .build(); | - temporary value is freed at the end of this state= ment Signed-off-by: Paolo Bonzini --- rust/migration/src/vmstate.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/rust/migration/src/vmstate.rs b/rust/migration/src/vmstate.rs index 05a833a8b7d..421a236194d 100644 --- a/rust/migration/src/vmstate.rs +++ b/rust/migration/src/vmstate.rs @@ -413,19 +413,30 @@ const fn phantom__(_: &T) -> ::core::marker::Phant= omData { }}; } =20 +/// Add a terminator to the fields in the arguments, and return +/// a reference to the resulting array of values. +#[macro_export] +macro_rules! vmstate_fields_ref { + ($($field:expr),*$(,)*) =3D> { + &[ + $($field),*, + $crate::bindings::VMStateField { + flags: $crate::bindings::VMStateFlags::VMS_END, + ..::common::zeroable::Zeroable::ZERO + } + ] + } +} + /// Helper macro to declare a list of /// ([`VMStateField`](`crate::bindings::VMStateField`)) into a static and = return /// a pointer to the array of values it created. #[macro_export] macro_rules! vmstate_fields { ($($field:expr),*$(,)*) =3D> {{ - static _FIELDS: &[$crate::bindings::VMStateField] =3D &[ + static _FIELDS: &[$crate::bindings::VMStateField] =3D $crate::vmst= ate_fields_ref!( $($field),*, - $crate::bindings::VMStateField { - flags: $crate::bindings::VMStateFlags::VMS_END, - ..::common::zeroable::Zeroable::ZERO - } - ]; + ); _FIELDS.as_ptr() }} } --=20 2.51.0 From nobody Sun Sep 28 16:28:08 2025 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=1758378660; cv=none; d=zohomail.com; s=zohoarc; b=GjjRxbfLEflwQUTOueI+jK1ethOi1RxyGEwpuXRMDYIR/BZFK04pM72afkE88dXW5VZf1Sqcy3WpOM6SAC8ShZE1LucArHWO+YL8lLrsJWrQksf+Ve8g7lYkBRMrsAHUmq81Gx6OfIBn5W/8RKkPYt5dCwxlmPOEwDgubtf/LKs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1758378660; 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=fIs8xQFHDs7W4qQkqDiO7oV8jErY0TH0WVxlppzb/1s=; b=AScOH+K7JcYef95EuPdP6/5bi/kqeACvBIX6CSP08n9pw80sdxhRyPa1pCTlutecMrHDennDz6nIfoCpJSacB+il1WMqHYTw3qK0AMo2Rd6jGQ83FttVPKkXsmOtXOdGNJonloPQk2J50ZpmrCd/K+/OJz2I5eh3gswD5ZzADb0= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758378660586340.3050041483723; Sat, 20 Sep 2025 07:31:00 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uzybU-0007Jr-SB; Sat, 20 Sep 2025 10:30:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uzybR-0007J0-SE for qemu-devel@nongnu.org; Sat, 20 Sep 2025 10:30: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 1uzybP-0005Sn-Db for qemu-devel@nongnu.org; Sat, 20 Sep 2025 10:30:17 -0400 Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-131-wp8ER5C3MPOMpzWDW1Bm-w-1; Sat, 20 Sep 2025 10:30:12 -0400 Received: by mail-wm1-f69.google.com with SMTP id 5b1f17b1804b1-45f2a1660fcso28088725e9.1 for ; Sat, 20 Sep 2025 07:30:12 -0700 (PDT) Received: from [192.168.10.48] ([151.95.47.123]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-467fc818e00sm84311545e9.0.2025.09.20.07.30.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 20 Sep 2025 07:30:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1758378614; 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=fIs8xQFHDs7W4qQkqDiO7oV8jErY0TH0WVxlppzb/1s=; b=CyHu+uyBpD4YArI8lxO1NqAZ2EKEyYPAQf22BaZ5hOg+cuaVnPLwkA+zd2wW9A1eHKSZGR 4FcDz7i9/ONXPBhWDwsrNfLbBasSIUcim7yUArBNNQghK1KOGPv4eh0q+sIU8SVbKJhqn3 deOBMEBRMs6gYHsYlKApfWqVmS1H7R8= X-MC-Unique: wp8ER5C3MPOMpzWDW1Bm-w-1 X-Mimecast-MFC-AGG-ID: wp8ER5C3MPOMpzWDW1Bm-w_1758378612 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758378611; x=1758983411; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=fIs8xQFHDs7W4qQkqDiO7oV8jErY0TH0WVxlppzb/1s=; b=atORjQ5TqFQRbbzWEaVOCOeVUTFE31NNg2mzzlYDcGQKGpmivP2n62FQXtHCRBFHfF 3LWXHcJzOwlVtPAVR1IYWE4le4bBi+y1gX8CzR7zx48gwbtmOFywajJV3+SeTJ3h2V4B jVytb4m56ow4hVY16zgNx6ZioN00mdmmdPN1Sg+A8IlVymYSrc/tE0D7WLXM+dLcd+id Mm4+PLRq7iQ8SiAQQIp/Xr+rBNt+ETbH4VN4DRB51/+rOYlEMA+25VNonMCXmtytPoYp eGtHU8YEpoKL6JHflgp7Hu3w4Vs+E0MxC6Hph5Kat+dDqU/8Ucv4kdIQw6PMNA2V98Md Or4Q== X-Gm-Message-State: AOJu0YxgEylchIzCfrXn3AH5ni6W51fbLq3tUbXRQRW6wCKg6mg8fXlU 5RCR43cUx4nvcWkUa7cF0T69zjBgaO+mKcj594uHyheRQQBbsO3u12/yziacDtCtdX8XZi7DOKV xo0eKHmK6jMMFbikrfK4GEA8XZg/MkXEbUk2UE/YhIsUpvjgEc1rcesdhUi1hEHsoopVf8XVxoo vWEHGq6eVD4JGpXUfz5UItd6TLyhkjoJ/FHmS9YmgH X-Gm-Gg: ASbGncvB5lGcZSZyRUFo8Pb2QtHY91mLl/vFqRjrC6ZwrcvTwIZ/b19wkF1+K/4SHIF 1ogO3aJi9wN/qEUaY0729Qz4pZ396VHZgQnsXeisiI9A9G15RahrvMBQOoQIHoEfJw/h8sj92J4 WDWPL5Uy5rhtEgPM6pfoqRSl6akgTbEYRPpMfzqIEIDy6S9IvgRjaM/qqMCgucLX4SDFNkKPobD z1Kds7L8mp+V48/zMApBgbzvsFzBYO7u/ryHEIA3HHkGI2UuXta1McS1PJruNrlo9/WR3xffQGy +on/sSOLolsbDIwTwwENCxKd5JIOXXnZsQhpf1jRzojvBjkflhav9hS8fG0ypwPy/DOu42JIBYu i08nDLnn4V73XqzOpJmQZNx+OOn1QJosSK0QzSQReH34= X-Received: by 2002:a05:600c:45d2:b0:45b:7d77:b592 with SMTP id 5b1f17b1804b1-467e6f36218mr68881545e9.12.1758378610612; Sat, 20 Sep 2025 07:30:10 -0700 (PDT) X-Google-Smtp-Source: AGHT+IF6yAihBDDQWq6K/o0tKGfwu/bfeX3ARyU00Vs5xEdNClC2xOeX5XKAVt22ovDYOp0oxPHHJA== X-Received: by 2002:a05:600c:45d2:b0:45b:7d77:b592 with SMTP id 5b1f17b1804b1-467e6f36218mr68881255e9.12.1758378609964; Sat, 20 Sep 2025 07:30:09 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, zhao1.liu@intel.com, manos.pitsidianakis@linaro.org Subject: [PATCH 4/7] rust: migration: add high-level migration wrappers Date: Sat, 20 Sep 2025 16:29:55 +0200 Message-ID: <20250920142958.181910-5-pbonzini@redhat.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20250920142958.181910-1-pbonzini@redhat.com> References: <20250920142958.181910-1-pbonzini@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.045, 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_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list 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-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1758378663213116600 Content-Type: text/plain; charset="utf-8" Instead of dealing with pre/post callbacks, allow devices to implement a snapshot/restore mechanism; this has two main advantages: - it can be easily implemented via procedural macros - there can be generic implementations to deal with various kinds of interior-mutable containers, from BqlRefCell to Mutex, so that C code does not see Rust concepts such as Mutex<>. Using it is easy; you can implement the snapshot/restore trait ToMigrationState and declare your state like: regs: Migratable> Migratable<> allows dereferencing to the underlying object with no run-time cost. Note that Migratable<> actually does not accept ToMigrationState, only the similar ToMigrationStateShared trait that the user will mostly not care about. This is required by the fact that pre/post callbacks take a &self, and ensures that the argument is a Mutex or BqlRefCell (including an array or Arc<> thereof). Signed-off-by: Paolo Bonzini Reviewed-by: Zhao Liu --- rust/Cargo.lock | 1 + rust/migration/Cargo.toml | 1 + rust/migration/meson.build | 1 + rust/migration/src/lib.rs | 3 + rust/migration/src/migratable.rs | 430 +++++++++++++++++++++++++++++++ 5 files changed, 436 insertions(+) create mode 100644 rust/migration/src/migratable.rs diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 960f603cedb..32db90066f1 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -140,6 +140,7 @@ version =3D "0.1.0" dependencies =3D [ "bql", "common", + "qemu_macros", "util", ] =20 diff --git a/rust/migration/Cargo.toml b/rust/migration/Cargo.toml index f4a86275152..8efce7a72cb 100644 --- a/rust/migration/Cargo.toml +++ b/rust/migration/Cargo.toml @@ -15,6 +15,7 @@ rust-version.workspace =3D true [dependencies] bql =3D { path =3D "../bql" } common =3D { path =3D "../common" } +qemu_macros =3D { path =3D "../qemu-macros" } util =3D { path =3D "../util" } =20 [lints] diff --git a/rust/migration/meson.build b/rust/migration/meson.build index 2f38da9220f..c258881790d 100644 --- a/rust/migration/meson.build +++ b/rust/migration/meson.build @@ -30,6 +30,7 @@ _migration_rs =3D static_library( [ 'src/lib.rs', 'src/bindings.rs', + 'src/migratable.rs', 'src/vmstate.rs', ], {'.' : _migration_bindings_inc_rs}, diff --git a/rust/migration/src/lib.rs b/rust/migration/src/lib.rs index 5f51dde4406..efe9896b619 100644 --- a/rust/migration/src/lib.rs +++ b/rust/migration/src/lib.rs @@ -2,5 +2,8 @@ =20 pub mod bindings; =20 +pub mod migratable; +pub use migratable::*; + pub mod vmstate; pub use vmstate::*; diff --git a/rust/migration/src/migratable.rs b/rust/migration/src/migratab= le.rs new file mode 100644 index 00000000000..d09eeb35f11 --- /dev/null +++ b/rust/migration/src/migratable.rs @@ -0,0 +1,430 @@ +// Copyright 2025 Red Hat, Inc. +// Author(s): Paolo Bonzini +// SPDX-License-Identifier: GPL-2.0-or-later + +use std::{ + fmt, + mem::size_of, + ptr::{self, addr_of, NonNull}, + sync::{Arc, Mutex}, +}; + +use bql::{BqlCell, BqlRefCell}; +use common::Zeroable; + +use crate::{ + bindings, vmstate_fields_ref, vmstate_of, InvalidError, VMState, VMSta= teDescriptionBuilder, +}; + +/// Enables QEMU migration support even when a type is wrapped with +/// synchronization primitives (like `Mutex`) that the C migration +/// code cannot directly handle. The trait provides methods to +/// extract essential state for migration and restore it after +/// migration completes. +/// +/// On top of extracting data from synchronization wrappers during save +/// and restoring it during load, it's also possible to use `ToMigrationSt= ate` +/// to convert runtime representations to migration-safe formats. +/// +/// # Examples +/// +/// ``` +/// use bql::BqlCell; +/// use migration::{InvalidError, ToMigrationState, VMState}; +/// # use migration::VMStateField; +/// +/// # #[derive(Debug, PartialEq, Eq)] +/// struct DeviceState { +/// counter: BqlCell, +/// enabled: bool, +/// } +/// +/// # #[derive(Debug)] +/// #[derive(Default)] +/// struct DeviceMigrationState { +/// counter: u32, +/// enabled: bool, +/// } +/// +/// # unsafe impl VMState for DeviceMigrationState { +/// # const BASE: VMStateField =3D ::common::Zeroable::ZERO; +/// # } +/// impl ToMigrationState for DeviceState { +/// type Migrated =3D DeviceMigrationState; +/// +/// fn snapshot_migration_state( +/// &self, +/// target: &mut Self::Migrated, +/// ) -> Result<(), InvalidError> { +/// target.counter =3D self.counter.get(); +/// target.enabled =3D self.enabled; +/// Ok(()) +/// } +/// +/// fn restore_migrated_state_mut( +/// &mut self, +/// source: Self::Migrated, +/// _version_id: u8, +/// ) -> Result<(), InvalidError> { +/// self.counter.set(source.counter); +/// self.enabled =3D source.enabled; +/// Ok(()) +/// } +/// } +/// # bql::start_test(); +/// # let dev =3D DeviceState { counter: 10.into(), enabled: true }; +/// # let mig =3D dev.to_migration_state().unwrap(); +/// # assert!(matches!(*mig, DeviceMigrationState { counter: 10, enabled: = true })); +/// # let mut dev2 =3D DeviceState { counter: 42.into(), enabled: false }; +/// # dev2.restore_migrated_state_mut(*mig, 1).unwrap(); +/// # assert_eq!(dev2, dev); +/// ``` +pub trait ToMigrationState { + /// The type used to represent the migrated state. + type Migrated: Default + VMState; + + /// Capture the current state into a migration-safe format, failing + /// if the state cannot be migrated. + fn snapshot_migration_state(&self, target: &mut Self::Migrated) -> Res= ult<(), InvalidError>; + + /// Restores state from a migrated representation, failing if the + /// state cannot be restored. + fn restore_migrated_state_mut( + &mut self, + source: Self::Migrated, + version_id: u8, + ) -> Result<(), InvalidError>; + + /// Convenience method to combine allocation and state capture + /// into a single operation. + fn to_migration_state(&self) -> Result, InvalidErr= or> { + let mut migrated =3D Box::::default(); + self.snapshot_migration_state(&mut migrated)?; + Ok(migrated) + } +} + +// Implementations for primitive types. Do not use a blanket implementati= on +// for all Copy types, because [T; N] is Copy if T is Copy; that would con= flict +// with the below implementation for arrays. +macro_rules! impl_for_primitive { + ($($t:ty),*) =3D> { + $( + impl ToMigrationState for $t { + type Migrated =3D Self; + + fn snapshot_migration_state( + &self, + target: &mut Self::Migrated, + ) -> Result<(), InvalidError> { + *target =3D *self; + Ok(()) + } + + fn restore_migrated_state_mut( + &mut self, + source: Self::Migrated, + _version_id: u8, + ) -> Result<(), InvalidError> { + *self =3D source; + Ok(()) + } + } + )* + }; +} + +impl_for_primitive!(u8, u16, u32, u64, i8, i16, i32, i64, bool); + +impl ToMigrationState for [T; N] +where + [T::Migrated; N]: Default, +{ + type Migrated =3D [T::Migrated; N]; + + fn snapshot_migration_state(&self, target: &mut Self::Migrated) -> Res= ult<(), InvalidError> { + for (item, target_item) in self.iter().zip(target.iter_mut()) { + item.snapshot_migration_state(target_item)?; + } + Ok(()) + } + + fn restore_migrated_state_mut( + &mut self, + source: Self::Migrated, + version_id: u8, + ) -> Result<(), InvalidError> { + for (item, source_item) in self.iter_mut().zip(source) { + item.restore_migrated_state_mut(source_item, version_id)?; + } + Ok(()) + } +} + +/// Extension trait for types that support migration state restoration +/// through interior mutability. +/// +/// This trait extends [`ToMigrationState`] for types that can restore +/// their state without requiring mutable access. While user structs +/// will generally use `ToMigrationState`, the device will have multiple +/// references and therefore the device struct has to employ an interior +/// mutability wrapper like [`Mutex`] or [`BqlRefCell`]. +/// +/// Anything that implements this trait can in turn be used within +/// [`Migratable`], which makes no assumptions on how to achieve mutable +/// access to the runtime state. +/// +/// # Examples +/// +/// ``` +/// use std::sync::Mutex; +/// +/// use migration::ToMigrationStateShared; +/// +/// let device_state =3D Mutex::new(42); +/// // Can restore without &mut access +/// device_state.restore_migrated_state(100, 1).unwrap(); +/// assert_eq!(*device_state.lock().unwrap(), 100); +/// ``` +pub trait ToMigrationStateShared: ToMigrationState { + /// Restores state from a migrated representation to an interior-mutab= le + /// object. Similar to `restore_migrated_state_mut`, but requires a + /// shared reference; therefore it can be used to restore a device's + /// state even though devices have multiple references to them. + fn restore_migrated_state( + &self, + source: Self::Migrated, + version_id: u8, + ) -> Result<(), InvalidError>; +} + +impl ToMigrationStateShared for= [T; N] +where + [T::Migrated; N]: Default, +{ + fn restore_migrated_state( + &self, + source: Self::Migrated, + version_id: u8, + ) -> Result<(), InvalidError> { + for (item, source_item) in self.iter().zip(source) { + item.restore_migrated_state(source_item, version_id)?; + } + Ok(()) + } +} + +impl ToMigrationState for Arc { + type Migrated =3D T::Migrated; + + fn snapshot_migration_state(&self, target: &mut Self::Migrated) -> Res= ult<(), InvalidError> { + (**self).snapshot_migration_state(target) + } + + fn restore_migrated_state_mut( + &mut self, + source: Self::Migrated, + version_id: u8, + ) -> Result<(), InvalidError> { + (**self).restore_migrated_state(source, version_id) + } +} + +impl ToMigrationStateShared for Arc { + fn restore_migrated_state( + &self, + source: Self::Migrated, + version_id: u8, + ) -> Result<(), InvalidError> { + (**self).restore_migrated_state(source, version_id) + } +} + +// Interior-mutable types only require ToMigrationState for the inner type! + +impl ToMigrationState for Mutex { + type Migrated =3D T::Migrated; + + fn snapshot_migration_state(&self, target: &mut Self::Migrated) -> Res= ult<(), InvalidError> { + self.lock().unwrap().snapshot_migration_state(target) + } + + fn restore_migrated_state_mut( + &mut self, + source: Self::Migrated, + version_id: u8, + ) -> Result<(), InvalidError> { + self.restore_migrated_state(source, version_id) + } +} + +impl ToMigrationStateShared for Mutex { + fn restore_migrated_state( + &self, + source: Self::Migrated, + version_id: u8, + ) -> Result<(), InvalidError> { + self.lock() + .unwrap() + .restore_migrated_state_mut(source, version_id) + } +} + +impl ToMigrationState for BqlRefCell { + type Migrated =3D T::Migrated; + + fn snapshot_migration_state(&self, target: &mut Self::Migrated) -> Res= ult<(), InvalidError> { + self.borrow().snapshot_migration_state(target) + } + + fn restore_migrated_state_mut( + &mut self, + source: Self::Migrated, + version_id: u8, + ) -> Result<(), InvalidError> { + self.get_mut() + .restore_migrated_state_mut(source, version_id) + } +} + +impl ToMigrationStateShared for BqlRefCell { + fn restore_migrated_state( + &self, + source: Self::Migrated, + version_id: u8, + ) -> Result<(), InvalidError> { + self.borrow_mut() + .restore_migrated_state_mut(source, version_id) + } +} + +/// A wrapper that enables QEMU migration for types with shared state. +/// +/// `Migratable` provides a bridge between Rust types that use interior +/// mutability (like `Mutex`) and QEMU's C-based migration infrastructu= re. +/// It manages the lifecycle of migration state and provides automatic +/// conversion between runtime and migration representations. +/// +/// ```ignore +/// # use std::sync::Mutex; +/// # use migration::Migratable; +/// +/// pub struct DeviceRegs { +/// status: u32, +/// } +/// +/// pub struct SomeDevice { +/// // ... +/// registers: Migratable>, +/// } +/// ``` +#[repr(C)] +pub struct Migratable { + /// Pointer to migration state, valid only during migration operations. + /// C vmstate does not support NULL pointers, so no `Option>`. + migration_state: BqlCell<*mut T::Migrated>, + + /// The runtime state that can be accessed during normal operation + runtime_state: T, +} + +impl std::ops::Deref for Migratable { + type Target =3D T; + + fn deref(&self) -> &Self::Target { + &self.runtime_state + } +} + +impl std::ops::DerefMut for Migratable { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.runtime_state + } +} + +impl Migratable { + /// Creates a new `Migratable` wrapper around the given runtime state. + /// + /// # Returns + /// A new `Migratable` instance ready for use and migration + pub fn new(runtime_state: T) -> Self { + Self { + migration_state: BqlCell::new(ptr::null_mut()), + runtime_state, + } + } + + fn pre_save(&self) -> Result<(), InvalidError> { + let state =3D self.runtime_state.to_migration_state()?; + self.migration_state.set(Box::into_raw(state)); + Ok(()) + } + + fn post_save(&self) -> Result<(), InvalidError> { + let state =3D unsafe { Box::from_raw(self.migration_state.take()) = }; + drop(state); + Ok(()) + } + + fn pre_load(&self) -> Result<(), InvalidError> { + self.migration_state + .set(Box::into_raw(Box::::default())); + Ok(()) + } + + fn post_load(&self, version_id: u8) -> Result<(), InvalidError> { + let state =3D unsafe { Box::from_raw(self.migration_state.take()) = }; + self.runtime_state + .restore_migrated_state(*state, version_id) + } +} + +impl fmt::Debug for Migratable +where + T::Migrated: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut struct_f =3D f.debug_struct("Migratable"); + struct_f.field("runtime_state", &self.runtime_state); + + let state =3D NonNull::new(self.migration_state.get()).map(|x| uns= afe { x.as_ref() }); + struct_f.field("migration_state", &state); + struct_f.finish() + } +} + +impl Default for Migratable { + fn default() -> Self { + Self::new(T::default()) + } +} + +impl Migratable { + const FIELD: bindings::VMStateField =3D vmstate_of!(Self, migration_st= ate); + + const FIELDS: &[bindings::VMStateField] =3D vmstate_fields_ref! { + Migratable::::FIELD + }; + + const VMSD: &'static bindings::VMStateDescription =3D VMStateDescripti= onBuilder::::new() + .version_id(1) + .minimum_version_id(1) + .pre_save(&Self::pre_save) + .pre_load(&Self::pre_load) + .post_save(&Self::post_save) + .post_load(&Self::post_load) + .fields(Self::FIELDS.as_ptr()) + .build() + .as_ref(); +} + +unsafe impl VMState for Migratable= { + const BASE: bindings::VMStateField =3D { + bindings::VMStateField { + vmsd: addr_of!(*Self::VMSD), + size: size_of::(), + flags: bindings::VMStateFlags::VMS_STRUCT, + ..Zeroable::ZERO + } + }; +} --=20 2.51.0 From nobody Sun Sep 28 16:28:08 2025 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=1758378677; cv=none; d=zohomail.com; s=zohoarc; b=JOE05S8Q4k/QP+6UESeFKI1z6XZCfHUCHyNHBiUqUtFl4zm/T3RqrOuoZew4P/WC3t2SvS3YwzjiwksbVP3IrLT0bioyVaVMqFYOGVeVxzlfz2aYFB6ZZ7m0FP5y21ZH4zWp/yD/wM0kg2GtZPslp5W85n4ddAdqYuzJIQicWlk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1758378677; 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=JYTQycbVXEUC503A1Xz7erE6PcHFAqKjXXmxKEfIz9U=; b=ElcCkMIIDnoUQG1si1C30LHNu7Bomvj4Y1OoAeh288YdcKwu8cvOjnEhPmGbIAyMM7lyVVhMs4+hvK9Y4J6TWaHAxscD4s1ImrLMmW9omtTK/OPgOCtOp6VSvEpgR2bfbNdG60B/EZzzpuh2/sjnQabI19rICSb+KT9vzgEWB94= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758378677189941.0689466077284; Sat, 20 Sep 2025 07:31:17 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uzybY-0007M2-VC; Sat, 20 Sep 2025 10:30:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uzybU-0007Jq-6Y for qemu-devel@nongnu.org; Sat, 20 Sep 2025 10:30: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 1uzybR-0005Sy-It for qemu-devel@nongnu.org; Sat, 20 Sep 2025 10:30:19 -0400 Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-605-q-Pg96MEPqOM3uVQS5LNXw-1; Sat, 20 Sep 2025 10:30:15 -0400 Received: by mail-wm1-f72.google.com with SMTP id 5b1f17b1804b1-45f2a1660fcso28089165e9.1 for ; Sat, 20 Sep 2025 07:30:15 -0700 (PDT) Received: from [192.168.10.48] ([151.95.47.123]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-461eefee9f3sm167826885e9.1.2025.09.20.07.30.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 20 Sep 2025 07:30:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1758378616; 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=JYTQycbVXEUC503A1Xz7erE6PcHFAqKjXXmxKEfIz9U=; b=J5Hf28nMIW6FyyEmY+WPwy+q8QkLuTcZWBkY6Yu9WdcR3MfkpmLN5d9e0Abd8np3Bw9Qxt jFe/Pd5tePk7dh16kwFYQ+HUk+zJ9UCyAbwGkHy9pmEPiBcrDMH44w1MIS4/ik2cM4BPZu z4lArwyaaVMuD4HeCc1JZxuIHENIAks= X-MC-Unique: q-Pg96MEPqOM3uVQS5LNXw-1 X-Mimecast-MFC-AGG-ID: q-Pg96MEPqOM3uVQS5LNXw_1758378614 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758378613; x=1758983413; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JYTQycbVXEUC503A1Xz7erE6PcHFAqKjXXmxKEfIz9U=; b=mhrdJ1vp8+k4SoeHr+OIsUC/+5SWwJvouPPYBWAi2EMv7xj4aYF33LiC17fYkoJqdc q54jJA9LtF/l3vqsqGWwlwT0uy9r7getPxo/x9s60SEKZJSl+loqkHKF/dGa2lJ9lgGI eP2k5t/b/24cwarGUAFgpqcZiOge31xJJF5+acdU7UJGYVZsM7oOUCErZwDm3ABmrRem TWQRP2DLfMgVYSL9Xt0FEcna0+OPv4vSu4/7u952qGOKJyUNhBCj0FrMesZXobVrDtxd RkMqzS58Rt8/A+z45FAJ6eaCYd0KsOIp8Yprwhji6MX2dL12JuAWT6pbD2xf4m1o2I8x WiSA== X-Gm-Message-State: AOJu0Yy3w5hYfly5WWVbJ+rfyTuGbTJiy5ISQCrQlNoQ1eefEwtBi6L5 6jvBSSBDf1wUu+Or+zffEnMJMVGEFd4ssNd1m46IgUq08FC2Px3Mv3ljy8mTXTu7/WMFE9CYDJr C1gOxENVkVNX5pS3Jb6i78p0zV4HvhjsboJa4ZqoVtqmClStbai2y9yRvfH8E0NV0S7GqoRd9GI u33Bju1kH0TewSaMjVy9qLDRbDBhm0BDNkbSRNMgfE X-Gm-Gg: ASbGncslpT/uQ4ckfie5eocapZLYm9dg8EZtWJ+L75YSAdA8QpMztqvuzkzQHv+mQMj KLl+abcaxa+HSaK3qJCF41yMwf9RUD5/zqX86FsHc3iPXKSb8SRDjD5qoDerpdhzZz9mPxycHxS XSSVSsdLdXQt1+QTUGFzf3fQlmGLLuvXQA/b8GhqsUk2E3++LZ9jHqSrsBb5aYyg6xxGwCnDpeW PaYbenpylwoGr/5RBVjB2c+Hl4MxyYrlmErsMhz/bfOvDhJYb4UIZIoC20yE6VOPk1l0yjiBwy+ saIuQOGzBjhcO+jQs4ybZ+sm96+J2xzohhy1mbr6Yro4RUa71MUG7x8RNoTWc166nXp/AzH3gp9 NYoy4fvwxDE4WY9bi5+ayhm2DEVB9OrXbKGwF8PSfpiw= X-Received: by 2002:a05:600c:68a:b0:467:f71c:292 with SMTP id 5b1f17b1804b1-467f71c05fdmr32757285e9.19.1758378613383; Sat, 20 Sep 2025 07:30:13 -0700 (PDT) X-Google-Smtp-Source: AGHT+IH4Tj6bIW6EqkKDvcZOVWeSh2+w+8AyKQ1vH1KzGzUwSKgFNCFGHx51GYGoicvS5mZmrNfbCA== X-Received: by 2002:a05:600c:68a:b0:467:f71c:292 with SMTP id 5b1f17b1804b1-467f71c05fdmr32757015e9.19.1758378612573; Sat, 20 Sep 2025 07:30:12 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, zhao1.liu@intel.com, manos.pitsidianakis@linaro.org Subject: [PATCH 5/7] rust: qemu-macros: add ToMigrationState derive macro Date: Sat, 20 Sep 2025 16:29:56 +0200 Message-ID: <20250920142958.181910-6-pbonzini@redhat.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20250920142958.181910-1-pbonzini@redhat.com> References: <20250920142958.181910-1-pbonzini@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.045, 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_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list 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-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1758378679248116600 Content-Type: text/plain; charset="utf-8" Add a macro that recursively builds the "migrated" version of a struct. Signed-off-by: Paolo Bonzini Reviewed-by: Zhao Liu --- rust/migration/meson.build | 2 +- rust/migration/src/lib.rs | 2 + rust/migration/src/migratable.rs | 12 +- rust/qemu-macros/src/lib.rs | 88 +++++++ rust/qemu-macros/src/migration_state.rs | 296 ++++++++++++++++++++++++ rust/qemu-macros/src/tests.rs | 112 ++++++++- 6 files changed, 507 insertions(+), 5 deletions(-) create mode 100644 rust/qemu-macros/src/migration_state.rs diff --git a/rust/migration/meson.build b/rust/migration/meson.build index c258881790d..3843b364c69 100644 --- a/rust/migration/meson.build +++ b/rust/migration/meson.build @@ -38,7 +38,7 @@ _migration_rs =3D static_library( override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_abi: 'rust', link_with: [_util_rs, _bql_rs], - dependencies: [common_rs], + dependencies: [common_rs, qemu_macros], ) =20 migration_rs =3D declare_dependency(link_with: [_migration_rs], diff --git a/rust/migration/src/lib.rs b/rust/migration/src/lib.rs index efe9896b619..c9bdf0d4133 100644 --- a/rust/migration/src/lib.rs +++ b/rust/migration/src/lib.rs @@ -2,6 +2,8 @@ =20 pub mod bindings; =20 +pub use qemu_macros::ToMigrationState; + pub mod migratable; pub use migratable::*; =20 diff --git a/rust/migration/src/migratable.rs b/rust/migration/src/migratab= le.rs index d09eeb35f11..fa25317eea8 100644 --- a/rust/migration/src/migratable.rs +++ b/rust/migration/src/migratable.rs @@ -79,6 +79,10 @@ /// # dev2.restore_migrated_state_mut(*mig, 1).unwrap(); /// # assert_eq!(dev2, dev); /// ``` +/// +/// More commonly, the trait is derived through the +/// [`derive(ToMigrationState)`](qemu_macros::ToMigrationState) procedural +/// macro. pub trait ToMigrationState { /// The type used to represent the migrated state. type Migrated: Default + VMState; @@ -305,13 +309,17 @@ fn restore_migrated_state( /// It manages the lifecycle of migration state and provides automatic /// conversion between runtime and migration representations. /// -/// ```ignore +/// ``` /// # use std::sync::Mutex; -/// # use migration::Migratable; +/// # use migration::{Migratable, ToMigrationState, VMState, VMStateField}; /// +/// #[derive(ToMigrationState)] /// pub struct DeviceRegs { /// status: u32, /// } +/// # unsafe impl VMState for DeviceRegsMigration { +/// # const BASE: VMStateField =3D ::common::Zeroable::ZERO; +/// # } /// /// pub struct SomeDevice { /// // ... diff --git a/rust/qemu-macros/src/lib.rs b/rust/qemu-macros/src/lib.rs index 7ab18061776..8151fb6d4e1 100644 --- a/rust/qemu-macros/src/lib.rs +++ b/rust/qemu-macros/src/lib.rs @@ -13,9 +13,13 @@ Attribute, Data, DeriveInput, Error, Field, Fields, FieldsUnnamed, Ide= nt, Meta, Path, Token, Variant, }; + mod bits; use bits::BitsConstInternal; =20 +mod migration_state; +use migration_state::MigrationStateDerive; + #[cfg(test)] mod tests; =20 @@ -393,3 +397,87 @@ pub fn bits_const_internal(ts: TokenStream) -> TokenSt= ream { .unwrap_or_else(syn::Error::into_compile_error) .into() } + +/// Derive macro for generating migration state structures and trait +/// implementations. +/// +/// This macro generates a migration state struct and implements the +/// `ToMigrationState` trait for the annotated struct, enabling state +/// serialization and restoration. Note that defining a `VMStateDescripti= on` +/// for the migration state struct is left to the user. +/// +/// # Container attributes +/// +/// The following attributes can be applied to the struct: +/// +/// - `#[migration_state(rename =3D CustomName)]` - Customizes the name of= the +/// generated migration struct. By default, the generated struct is named +/// `{OriginalName}Migration`. +/// +/// # Field attributes +/// +/// The following attributes can be applied to individual fields: +/// +/// - `#[migration_state(omit)]` - Excludes the field from the migration s= tate +/// entirely. +/// +/// - `#[migration_state(into(Type))]` - Converts the field using `.into()` +/// during both serialization and restoration. +/// +/// - `#[migration_state(try_into(Type))]` - Converts the field using +/// `.try_into()` during both serialization and restoration. Returns +/// `InvalidError` on conversion failure. +/// +/// - `#[migration_state(clone)]` - Clones the field value. +/// +/// Fields without any attributes use `ToMigrationState` recursively; note= that +/// this is a simple copy for types that implement `Copy`. +/// +/// # Attribute compatibility +/// +/// - `omit` cannot be used with any other attributes +/// - only one of `into(Type)`, `try_into(Type)` can be used, but they can= be +/// coupled with `clone`. +/// +/// # Examples +/// +/// Basic usage: +/// ```ignore +/// #[derive(ToMigrationState)] +/// struct MyStruct { +/// field1: u32, +/// field2: Timer, +/// } +/// ``` +/// +/// With attributes: +/// ```ignore +/// #[derive(ToMigrationState)] +/// #[migration_state(rename =3D CustomMigration)] +/// struct MyStruct { +/// #[migration_state(omit)] +/// runtime_field: u32, +/// +/// #[migration_state(clone)] +/// shared_data: String, +/// +/// #[migration_state(into(Cow<'static, str>), clone)] +/// converted_field: String, +/// +/// #[migration_state(try_into(i8))] +/// fallible_field: u32, +/// +/// // Default: use ToMigrationState trait recursively +/// nested_field: NestedStruct, +/// +/// // Primitive types have a default implementation of ToMigrationSta= te +/// simple_field: u32, +/// } +/// ``` +#[proc_macro_derive(ToMigrationState, attributes(migration_state))] +pub fn derive_to_migration_state(input: TokenStream) -> TokenStream { + let input =3D parse_macro_input!(input as DeriveInput); + MigrationStateDerive::expand(input) + .unwrap_or_else(syn::Error::into_compile_error) + .into() +} diff --git a/rust/qemu-macros/src/migration_state.rs b/rust/qemu-macros/src= /migration_state.rs new file mode 100644 index 00000000000..89feae1e767 --- /dev/null +++ b/rust/qemu-macros/src/migration_state.rs @@ -0,0 +1,296 @@ +use std::borrow::Cow; + +use proc_macro2::TokenStream; +use quote::{format_ident, quote, ToTokens}; +use syn::{spanned::Spanned, DeriveInput, Error, Field, Ident, Result, Type= }; + +use crate::get_fields; + +#[derive(Debug, Default)] +enum ConversionMode { + #[default] + None, + Omit, + Into(Type), + TryInto(Type), + ToMigrationState, +} + +impl ConversionMode { + fn target_type(&self, original_type: &Type) -> TokenStream { + match self { + ConversionMode::Into(ty) | ConversionMode::TryInto(ty) =3D> ty= .to_token_stream(), + ConversionMode::ToMigrationState =3D> { + quote! { <#original_type as ToMigrationState>::Migrated } + } + _ =3D> original_type.to_token_stream(), + } + } +} + +#[derive(Debug, Default)] +struct ContainerAttrs { + rename: Option, +} + +impl ContainerAttrs { + fn parse_from(&mut self, attrs: &[syn::Attribute]) -> Result<()> { + use attrs::{set, with, Attrs}; + Attrs::new() + .once("rename", with::eq(set::parse(&mut self.rename))) + .parse_attrs("migration_state", attrs)?; + Ok(()) + } + + fn parse(attrs: &[syn::Attribute]) -> Result { + let mut container_attrs =3D Self::default(); + container_attrs.parse_from(attrs)?; + Ok(container_attrs) + } +} + +#[derive(Debug, Default)] +struct FieldAttrs { + conversion: ConversionMode, + clone: bool, +} + +impl FieldAttrs { + fn parse_from(&mut self, attrs: &[syn::Attribute]) -> Result<()> { + let mut omit_flag =3D false; + let mut into_type: Option =3D None; + let mut try_into_type: Option =3D None; + + use attrs::{set, with, Attrs}; + Attrs::new() + .once("omit", set::flag(&mut omit_flag)) + .once("into", with::paren(set::parse(&mut into_type))) + .once("try_into", with::paren(set::parse(&mut try_into_type))) + .once("clone", set::flag(&mut self.clone)) + .parse_attrs("migration_state", attrs)?; + + self.conversion =3D match (omit_flag, into_type, try_into_type, se= lf.clone) { + // Valid combinations of attributes first... + (true, None, None, false) =3D> ConversionMode::Omit, + (false, Some(ty), None, _) =3D> ConversionMode::Into(ty), + (false, None, Some(ty), _) =3D> ConversionMode::TryInto(ty), + (false, None, None, true) =3D> ConversionMode::None, // clone = without conversion + (false, None, None, false) =3D> ConversionMode::ToMigrationSta= te, // default behavior + + // ... then the error cases + (true, _, _, _) =3D> { + return Err(Error::new( + attrs[0].span(), + "ToMigrationState: omit cannot be used with other attr= ibutes", + )); + } + (_, Some(_), Some(_), _) =3D> { + return Err(Error::new( + attrs[0].span(), + "ToMigrationState: into and try_into attributes cannot= be used together", + )); + } + }; + + Ok(()) + } + + fn parse(attrs: &[syn::Attribute]) -> Result { + let mut field_attrs =3D Self::default(); + field_attrs.parse_from(attrs)?; + Ok(field_attrs) + } +} + +#[derive(Debug)] +struct MigrationStateField { + name: Ident, + original_type: Type, + attrs: FieldAttrs, +} + +impl MigrationStateField { + fn maybe_clone(&self, mut value: TokenStream) -> TokenStream { + if self.attrs.clone { + value =3D quote! { #value.clone() }; + } + value + } + + fn generate_migration_state_field(&self) -> TokenStream { + let name =3D &self.name; + let field_type =3D self.attrs.conversion.target_type(&self.origina= l_type); + + quote! { + pub #name: #field_type, + } + } + + fn generate_snapshot_field(&self) -> TokenStream { + let name =3D &self.name; + let value =3D self.maybe_clone(quote! { self.#name }); + + match &self.attrs.conversion { + ConversionMode::Omit =3D> { + unreachable!("Omitted fields are filtered out during proce= ssing") + } + ConversionMode::None =3D> quote! { + target.#name =3D #value; + }, + ConversionMode::Into(_) =3D> quote! { + target.#name =3D #value.into(); + }, + ConversionMode::TryInto(_) =3D> quote! { + target.#name =3D #value.try_into().map_err(|_| migration::= InvalidError)?; + }, + ConversionMode::ToMigrationState =3D> quote! { + self.#name.snapshot_migration_state(&mut target.#name)?; + }, + } + } + + fn generate_restore_field(&self) -> TokenStream { + let name =3D &self.name; + + match &self.attrs.conversion { + ConversionMode::Omit =3D> { + unreachable!("Omitted fields are filtered out during proce= ssing") + } + ConversionMode::None =3D> quote! { + self.#name =3D #name; + }, + ConversionMode::Into(_) =3D> quote! { + self.#name =3D #name.into(); + }, + ConversionMode::TryInto(_) =3D> quote! { + self.#name =3D #name.try_into().map_err(|_| migration::Inv= alidError)?; + }, + ConversionMode::ToMigrationState =3D> quote! { + self.#name.restore_migrated_state_mut(#name, version_id)?; + }, + } + } +} + +#[derive(Debug)] +pub struct MigrationStateDerive { + input: DeriveInput, + fields: Vec, + container_attrs: ContainerAttrs, +} + +impl MigrationStateDerive { + fn parse(input: DeriveInput) -> Result { + let container_attrs =3D ContainerAttrs::parse(&input.attrs)?; + let fields =3D get_fields(&input, "ToMigrationState")?; + let fields =3D Self::process_fields(fields)?; + + Ok(Self { + input, + fields, + container_attrs, + }) + } + + fn process_fields( + fields: &syn::punctuated::Punctuated, + ) -> Result> { + let processed =3D fields + .iter() + .map(|field| { + let attrs =3D FieldAttrs::parse(&field.attrs)?; + Ok((field, attrs)) + }) + .collect::>>()? + .into_iter() + .filter(|(_, attrs)| !matches!(attrs.conversion, ConversionMod= e::Omit)) + .map(|(field, attrs)| MigrationStateField { + name: field.ident.as_ref().unwrap().clone(), + original_type: field.ty.clone(), + attrs, + }) + .collect(); + + Ok(processed) + } + + fn migration_state_name(&self) -> Cow<'_, Ident> { + match &self.container_attrs.rename { + Some(rename) =3D> Cow::Borrowed(rename), + None =3D> Cow::Owned(format_ident!("{}Migration", &self.input.= ident)), + } + } + + fn generate_migration_state_struct(&self) -> TokenStream { + let name =3D self.migration_state_name(); + let fields =3D self + .fields + .iter() + .map(MigrationStateField::generate_migration_state_field); + + quote! { + #[derive(Default)] + pub struct #name { + #(#fields)* + } + } + } + + fn generate_snapshot_migration_state(&self) -> TokenStream { + let fields =3D self + .fields + .iter() + .map(MigrationStateField::generate_snapshot_field); + + quote! { + fn snapshot_migration_state(&self, target: &mut Self::Migrated= ) -> Result<(), migration::InvalidError> { + #(#fields)* + Ok(()) + } + } + } + + fn generate_restore_migrated_state(&self) -> TokenStream { + let names: Vec<_> =3D self.fields.iter().map(|f| &f.name).collect(= ); + let fields =3D self + .fields + .iter() + .map(MigrationStateField::generate_restore_field); + + quote! { + fn restore_migrated_state_mut(&mut self, source: Self::Migrate= d, version_id: u8) -> Result<(), migration::InvalidError> { + let Self::Migrated { #(#names),* } =3D source; + #(#fields)* + Ok(()) + } + } + } + + fn generate(&self) -> TokenStream { + let struct_name =3D &self.input.ident; + let generics =3D &self.input.generics; + + let (impl_generics, ty_generics, where_clause) =3D generics.split_= for_impl(); + let name =3D self.migration_state_name(); + let migration_state_struct =3D self.generate_migration_state_struc= t(); + let snapshot_impl =3D self.generate_snapshot_migration_state(); + let restore_impl =3D self.generate_restore_migrated_state(); + + quote! { + #migration_state_struct + + impl #impl_generics ToMigrationState for #struct_name #ty_gene= rics #where_clause { + type Migrated =3D #name; + + #snapshot_impl + + #restore_impl + } + } + } + + pub fn expand(input: DeriveInput) -> Result { + let tokens =3D Self::parse(input)?.generate(); + Ok(tokens) + } +} diff --git a/rust/qemu-macros/src/tests.rs b/rust/qemu-macros/src/tests.rs index 00a106612fc..1ce43aa568e 100644 --- a/rust/qemu-macros/src/tests.rs +++ b/rust/qemu-macros/src/tests.rs @@ -7,7 +7,7 @@ use super::*; =20 macro_rules! derive_compile_fail { - ($derive_fn:ident, $input:expr, $($error_msg:expr),+ $(,)?) =3D> {{ + ($derive_fn:path, $input:expr, $($error_msg:expr),+ $(,)?) =3D> {{ let input: proc_macro2::TokenStream =3D $input; let error_msg =3D &[$( quote! { ::core::compile_error! { $error_ms= g } } ),*]; let derive_fn: fn(input: syn::DeriveInput) -> Result =3D @@ -24,7 +24,7 @@ macro_rules! derive_compile_fail { } =20 macro_rules! derive_compile { - ($derive_fn:ident, $input:expr, $($expected:tt)*) =3D> {{ + ($derive_fn:path, $input:expr, $($expected:tt)*) =3D> {{ let input: proc_macro2::TokenStream =3D $input; let expected: proc_macro2::TokenStream =3D $($expected)*; let derive_fn: fn(input: syn::DeriveInput) -> Result =3D @@ -244,3 +244,111 @@ fn try_from(value: u8) -> Result { } ); } + +#[test] +fn test_derive_to_migration_state() { + derive_compile_fail!( + MigrationStateDerive::expand, + quote! { + struct MyStruct { + #[migration_state(omit, clone)] + bad: u32, + } + }, + "ToMigrationState: omit cannot be used with other attributes" + ); + derive_compile_fail!( + MigrationStateDerive::expand, + quote! { + struct MyStruct { + #[migration_state(into)] + bad: u32, + } + }, + "unexpected end of input, expected parentheses" + ); + derive_compile_fail!( + MigrationStateDerive::expand, + quote! { + struct MyStruct { + #[migration_state(into(String), try_into(String))] + bad: &'static str, + } + }, + "ToMigrationState: into and try_into attributes cannot be used tog= ether" + ); + derive_compile!( + MigrationStateDerive::expand, + quote! { + #[migration_state(rename =3D CustomMigration)] + struct MyStruct { + #[migration_state(omit)] + runtime_field: u32, + + #[migration_state(clone)] + shared_data: String, + + #[migration_state(into(Cow<'static, str>), clone)] + converted_field: String, + + #[migration_state(try_into(i8))] + fallible_field: u32, + + nested_field: NestedStruct, + simple_field: u32, + } + }, + quote! { + #[derive(Default)] + pub struct CustomMigration { + pub shared_data: String, + pub converted_field: Cow<'static, str>, + pub fallible_field: i8, + pub nested_field: ::Migr= ated, + pub simple_field: ::Migrated, + } + impl ToMigrationState for MyStruct { + type Migrated =3D CustomMigration; + fn snapshot_migration_state( + &self, + target: &mut Self::Migrated + ) -> Result<(), migration::InvalidError> { + target.shared_data =3D self.shared_data.clone(); + target.converted_field =3D self.converted_field.clone(= ).into(); + target.fallible_field =3D self + .fallible_field + .try_into() + .map_err(|_| migration::InvalidError)?; + self.nested_field + .snapshot_migration_state(&mut target.nested_field= )?; + self.simple_field + .snapshot_migration_state(&mut target.simple_field= )?; + Ok(()) + } + fn restore_migrated_state_mut( + &mut self, + source: Self::Migrated, + version_id: u8 + ) -> Result<(), migration::InvalidError> { + let Self::Migrated { + shared_data, + converted_field, + fallible_field, + nested_field, + simple_field + } =3D source; + self.shared_data =3D shared_data; + self.converted_field =3D converted_field.into(); + self.fallible_field =3D fallible_field + .try_into() + .map_err(|_| migration::InvalidError)?; + self.nested_field + .restore_migrated_state_mut(nested_field, version_= id)?; + self.simple_field + .restore_migrated_state_mut(simple_field, version_= id)?; + Ok(()) + } + } + } + ); +} --=20 2.51.0 From nobody Sun Sep 28 16:28:08 2025 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=1758378691; cv=none; d=zohomail.com; s=zohoarc; b=a9pz+lzQDbfzNB9eXEuX3TwPgEIKHDg70HcT3HiuVAnJNPVrNnHRyvPseAbeSanWsZ4SvjDN7oMBpTx0uCPHa1A4aV/HeEbiUNuRhjvoQI+LTSpExDdGgW4ibV2bSWxt0fzxr/+JSiJ9R9x4FK2ulc8VSzbnQjD2xiocxTM1B8Y= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1758378691; 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=9pbC1Ps+dAzTsqIP6WX+wZIGyK3TQi+fmkaYLXqHka4=; b=fFW2RoMoQ9/u6wOkDSTgMWTpgce96Da1dX8gKDy++JpHo+d7Y5TNiS1AUo8O+Z/DSvi9GZsgx4ctQ64Rn9iE/yf85vL/LZ+KA5atly5bMmtrzR65IKXJy8iKBziHHsa9qW8C1B3Hs/2QzJGr444Em3yK5Rd8rt0e5P3LefOvqlY= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758378691498913.9450512378636; Sat, 20 Sep 2025 07:31:31 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uzyba-0007Nd-Ud; Sat, 20 Sep 2025 10:30:26 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uzybY-0007L8-0r for qemu-devel@nongnu.org; Sat, 20 Sep 2025 10:30:24 -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 1uzybV-0005Td-BI for qemu-devel@nongnu.org; Sat, 20 Sep 2025 10:30:23 -0400 Received: from mail-wr1-f71.google.com (mail-wr1-f71.google.com [209.85.221.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-79-ynGdb7-dNHm4Zw015DGTDg-1; Sat, 20 Sep 2025 10:30:18 -0400 Received: by mail-wr1-f71.google.com with SMTP id ffacd0b85a97d-3ecdfe971abso3387025f8f.2 for ; Sat, 20 Sep 2025 07:30:17 -0700 (PDT) Received: from [192.168.10.48] ([151.95.47.123]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3ee0fbf3bfcsm12532849f8f.58.2025.09.20.07.30.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 20 Sep 2025 07:30:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1758378620; 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=9pbC1Ps+dAzTsqIP6WX+wZIGyK3TQi+fmkaYLXqHka4=; b=gd049jE5FnPGLTdA/Z8nXgxtvJLMvk9aL74b9A5Ju7Bv/SH3MLgHls0VmuFeDcnq2T23Hn lq/1KZA0/UUhvqMJwpQNyigqs+0lvcnXf3RL0SMf+V/VwG7EMmrrFzpkeu7bFJZhv6nzmk Si21c1WYfirqQwOX4+BpYZ5mPRkCL9M= X-MC-Unique: ynGdb7-dNHm4Zw015DGTDg-1 X-Mimecast-MFC-AGG-ID: ynGdb7-dNHm4Zw015DGTDg_1758378617 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758378616; x=1758983416; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=9pbC1Ps+dAzTsqIP6WX+wZIGyK3TQi+fmkaYLXqHka4=; b=b1+pBsdYAbc6scu/yMOx0pHKak0Xl5fTjWbkeACWik4mC53Ig6dh73Ev5Arg1jNajW v21Y1mQGvHCwwRfHb8glDMuiNSwPrRbbaPQBR3lyV9t+Ic+7tmYVhX5AbIjB40Xvndp1 nk7KW2Sa8sRX9Eg6jCKFn28aKbz5p9t4E5V12wd+Jtsst3Zmf47/mdZsfwGjPZCVE0ph WQEHcfUMToH8/He7c0oQlWgpYsiQ4akgsLuPPVCc3fS90Q9l9BMAOuw9b9boNIh0Ul9r fHpv1hoVIRZM0qo+ePyYCsUG5bnPrUN7vkcL8PDc1Ve7EVtuVt1AeY2uql7iyAPZhJAp LRVA== X-Gm-Message-State: AOJu0YwTYWZBwNvZaoNaQu3h6n8BRP2ryAGOsDdw2HZsNSAP75LRTvUM 8wy3FhQUTeTwUvPlmeVT9PrdH0y3L4LWDDaUSd3M5GHBywMzMzVZHTySjpSCWOCd1Vhz2r5cmkV VMNRMRN/EDf5LgFc9sxVF/NWqzis3ZffTiZJGPdxKHEvG9Yhnoge16WwE7iAlUK2rCi5v1Uo/W/ fa6njtr/j6+5SrkctjwgrPHUWIzRqad8KVOlsPu2Wp X-Gm-Gg: ASbGncsC1D/HwF3pu1KvUP5y1EwODHED4eFis/HPgDRCGNW0hPDt6zHC6/UyR91zKQ8 0VJrxSD6MzG2lLKQHwtuVxb/C/AkCydkPIaYV4SMh1ASrrT1LDFWa3BA9jSynZu5fIRwR4/mwnW /rQyyX9wDYrBBQXi2vWBL7o55IuhreQZPWoxmXW2oftvwmax6nbQquF9ZQSym1s7gUJbG4FQbnm G3mDrO2XsaANnqBy+y3HiIcEicNx+0P+lb7rwGmYNrvhA5XpnaeaA4TFr8eFR0gMoX745GrSW7w Iy8TM4tWJJjWhsNDexpSh/0CJjOncjVAAhadUEvNVHByU6y+TVbXMcPHIzCL6UGBHrrndg/OXG4 RU13vxuKBHGhZGaUxJ18Wah30xgh00we72weMqc8J8RA= X-Received: by 2002:a05:600c:4ed1:b0:45d:dbf4:8880 with SMTP id 5b1f17b1804b1-467eb048bbcmr52826305e9.27.1758378615804; Sat, 20 Sep 2025 07:30:15 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFtpQlVrIBjGRymU78+iTO0yanR7FsyLJIrN/bi/H48KCbH18Ao8LVGUxN9TCaPjw6s6r9nVw== X-Received: by 2002:a05:600c:4ed1:b0:45d:dbf4:8880 with SMTP id 5b1f17b1804b1-467eb048bbcmr52826105e9.27.1758378615388; Sat, 20 Sep 2025 07:30:15 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, zhao1.liu@intel.com, manos.pitsidianakis@linaro.org Subject: [PATCH 6/7] rust: migration: implement ToMigrationState for Timer Date: Sat, 20 Sep 2025 16:29:57 +0200 Message-ID: <20250920142958.181910-7-pbonzini@redhat.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20250920142958.181910-1-pbonzini@redhat.com> References: <20250920142958.181910-1-pbonzini@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.045, 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_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list 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-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1758378693317116600 Content-Type: text/plain; charset="utf-8" Timer is a complex struct, allow adding it to a struct that uses #[derive(ToMigrationState)]; similar to vmstate_timer, only the expiration time has to be preserved. Signed-off-by: Paolo Bonzini --- rust/migration/src/migratable.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/rust/migration/src/migratable.rs b/rust/migration/src/migratab= le.rs index fa25317eea8..c4ad4f73d5c 100644 --- a/rust/migration/src/migratable.rs +++ b/rust/migration/src/migratable.rs @@ -202,6 +202,37 @@ fn restore_migrated_state( ) -> Result<(), InvalidError>; } =20 +impl ToMigrationState for util::timer::Timer { + type Migrated =3D i64; + + fn snapshot_migration_state(&self, target: &mut i64) -> Result<(), Inv= alidError> { + // SAFETY: as_ptr() is unsafe to ensure that the caller reasons ab= out + // the pinning of the data inside the Opaque<>. Here all we do is + // access a field. + *target =3D unsafe { &*self.as_ptr() }.expire_time; + Ok(()) + } + + fn restore_migrated_state_mut( + &mut self, + source: Self::Migrated, + version_id: u8, + ) -> Result<(), InvalidError> { + self.restore_migrated_state(source, version_id) + } +} + +impl ToMigrationStateShared for util::timer::Timer { + fn restore_migrated_state(&self, source: i64, _version_id: u8) -> Resu= lt<(), InvalidError> { + if source >=3D 0 { + self.modify(source as u64); + } else { + self.delete(); + } + Ok(()) + } +} + impl ToMigrationStateShared for= [T; N] where [T::Migrated; N]: Default, --=20 2.51.0 From nobody Sun Sep 28 16:28:08 2025 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=1758378699; cv=none; d=zohomail.com; s=zohoarc; b=WfslFV6Xw5uXK/kbl4ibcE427xUSxQ7NRPsDRqCHNL3nmKqCZbSz+pZXMoyzVmzwPOJpi01llgpQU1xF1ieg3ZSlJ4HRxRI6aKWSltueh6G9GFANwa/D37myCy1JRdzGyfjyBx/ucL5nM4h95xgO23Zd0mcp8T3MXIonX4ghgH4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1758378699; 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=l9jcGdX1lSvJdDQcVF4FUrlARni1t0sPnSGCmO+JHDo=; b=KW8wplS491yl3GCAr3XEiex+nf0q+ubsgYREC2C8Ph5wG8TKyCUkaVvi0JuU2+VQNT7bSUGxG1ruYyi4uZ2xImE5WFA08BWrv7eHdl03W+AAX+QR/sUAt/fkVAZpWrTvWjtEaU0M23SDFTudVgLPfF1WrieS/U/JMvv9/FDiNCE= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758378699637313.6642899075158; Sat, 20 Sep 2025 07:31:39 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uzybf-0007T1-DX; Sat, 20 Sep 2025 10:30:31 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uzybd-0007Rr-Lu for qemu-devel@nongnu.org; Sat, 20 Sep 2025 10:30:30 -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 1uzybW-0005U1-Iv for qemu-devel@nongnu.org; Sat, 20 Sep 2025 10:30:28 -0400 Received: from mail-wr1-f70.google.com (mail-wr1-f70.google.com [209.85.221.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-126-WEdMH3o4Pf2RjuC79T_biw-1; Sat, 20 Sep 2025 10:30:20 -0400 Received: by mail-wr1-f70.google.com with SMTP id ffacd0b85a97d-3ee888281c3so1647070f8f.3 for ; Sat, 20 Sep 2025 07:30:20 -0700 (PDT) Received: from [192.168.10.48] ([151.95.47.123]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3ee07407fa3sm12145305f8f.21.2025.09.20.07.30.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 20 Sep 2025 07:30:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1758378621; 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=l9jcGdX1lSvJdDQcVF4FUrlARni1t0sPnSGCmO+JHDo=; b=WqDBvlhCakKgem+C+xKH3sFtIcbTbrcmehkRCQq2pLnZtD2VzlFs1AmSLPdJVeQIqnFBrg x3DI42EwGtuMDuWQWbhWFSJo1ue+9ZJS1bMY8XGFwHOrSoFVdyUXXcHV+AbUthy6EVKgW5 YY/walyyT7OiCLlg25jkdXhjb9R022w= X-MC-Unique: WEdMH3o4Pf2RjuC79T_biw-1 X-Mimecast-MFC-AGG-ID: WEdMH3o4Pf2RjuC79T_biw_1758378619 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758378618; x=1758983418; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=l9jcGdX1lSvJdDQcVF4FUrlARni1t0sPnSGCmO+JHDo=; b=jUhwKZBm7vJyujgQAysNW8OSvPY0XF6jBWWnTyqjlEoScYJhT8kz9tM15yVmeeEwXD WydNtzDVb0YRQjDPOXKtV2YdpqgQyo+R5TmXTW9lHl+3FRCIfE/YpHHf7OtA6vNp7vt3 5qiAELT69Nm8j0Ymod+1jlAtAml7P9agYUG/tWQrHeXo44/+Jb281Rx7Ju8b3S/jxCWX Zn71Ifu/7T3EPSDJUXDG3Q/wBGcUhFZPphJEnpjaPVKioG4sQeXJnt/HRLtkXPPiEMcb DfokpjLoqrrwrCgiKmMswtaAJpc18iloBzFj+1un6UdVK51EIxAvGnoV6FFjbG4yEBQ5 Q7lA== X-Gm-Message-State: AOJu0YyCOmZ7PAVR+cV4rfFw4J+OPprmxhU/Zi+vv7u73Q3hNtAGnXYm TAIxdVzF2bdKXu6uQBfKesuQc/BPFci52h/VINhtLed+XNExhyoBcir2nmovO4xo9/5T4sVbACo IyuBbSu9eRwr1nlRTZ7LfSxv8rvpDHr8e4utwFzr5jn1wwyFGTqCbQ9Om0/ukoOcCQ2DuUQA1CO ciWaolqc5og/+J37Z9PCMVzJp6Jct25Ctc0QmlPL2O X-Gm-Gg: ASbGnct6a1ylUmHv1aNGxOG+WCiZr52Jk40uSWOiqsB4nHh41vBxOARMIQKUTsLmAJy R+0poRyAgmY34FRIcny5hFceAbK2+yBK1DDz0PtEpwc2hRuHByoHTRQN1MMrEMABQwbnvD1kYrn GEUb3D/Wq9mYEM7V3FwxhJdV4/nWljLrCC5Inr27twpvILbza174d60dv7IhsF0qc+Osrj4Zpok JrBVHilAHTXxGzFcd2X5Cj1cSpVYhyxMHd75z18mqPyzaZgvoXg/l8VP06ltXQpDePLTps7x33+ +fNu/mbs6LowzFnFkq/eAlc43Zxb7yB8TjiOH1CkXGh5rt7rg2CMCCPuGx0374UXwgtB1lKnr3O sr+xoS7zFvj8VDjMJTuyhhdkc173pCsf0SASnjbhUbj8= X-Received: by 2002:a05:6000:24c9:b0:3ec:ce37:3a6d with SMTP id ffacd0b85a97d-3ee857699acmr5746400f8f.47.1758378618448; Sat, 20 Sep 2025 07:30:18 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGVsQCkxTEWRDRQztw0Hn3LuLOS8XxwHM2e/j9Mx0kRIkEmI+325YL5RSZSPJLHN5BW03f3fg== X-Received: by 2002:a05:6000:24c9:b0:3ec:ce37:3a6d with SMTP id ffacd0b85a97d-3ee857699acmr5746385f8f.47.1758378617995; Sat, 20 Sep 2025 07:30:17 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, zhao1.liu@intel.com, manos.pitsidianakis@linaro.org Subject: [PATCH 7/7] rust: migration: implement ToMigrationState as part of impl_vmstate_bitsized Date: Sat, 20 Sep 2025 16:29:58 +0200 Message-ID: <20250920142958.181910-8-pbonzini@redhat.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20250920142958.181910-1-pbonzini@redhat.com> References: <20250920142958.181910-1-pbonzini@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.045, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list 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-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1758378701402116601 Content-Type: text/plain; charset="utf-8" This is most likely desirable, and is the easiest way to migrate a bit-sized value without peeking at the innards of the bilge crate. Signed-off-by: Paolo Bonzini --- rust/migration/src/vmstate.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/rust/migration/src/vmstate.rs b/rust/migration/src/vmstate.rs index 421a236194d..882dab746fc 100644 --- a/rust/migration/src/vmstate.rs +++ b/rust/migration/src/vmstate.rs @@ -295,6 +295,25 @@ unsafe impl $crate::vmstate::VMState for $type { as ::bilge::prelude::Number>::Un= derlyingType as $crate::vmstate::VMState>::VAR= RAY_FLAG; } + + impl $crate::migratable::ToMigrationState for $type { + type Migrated =3D <<$type as ::bilge::prelude::Bitsized>::Arbi= traryInt + as ::bilge::prelude::Number>::Un= derlyingType; + + fn snapshot_migration_state(&self, target: &mut Self::Migrated= ) -> Result<(), $crate::InvalidError> { + *target =3D Self::Migrated::from(*self); + Ok(()) + } + + fn restore_migrated_state_mut( + &mut self, + source: Self::Migrated, + version_id: u8, + ) -> Result<(), $crate::InvalidError> { + *self =3D Self::from(source); + Ok(()) + } + } }; } =20 --=20 2.51.0