From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733747901; cv=none; d=zohomail.com; s=zohoarc; b=BBNKJDTXOAQ1jxrK8Getvtky967w7ghZfUd6i5Yffc1fH9ZMwl+nYisBLC8exvKFHKBjwPYNYrAlB3bSENo9jWtRpghfzBQMqUHzQsTQThiVZsHnEEQ4ONoMkpLw3YYEwmYaAN5FziT0mgO6Y8UuuFtl8DfrX0h2x2MWaQLGljw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733747901; 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=EK+6NhPLRnfB+w3ii90rEiEDD8OWs1ZakSYY9qmOsvM=; b=UgceXbY/H8V2uOkUE3cYvnAfEMMXJGe10poJTA7AmIUi5gUruAt2ziKIKnz2/L0UwtXyyitQXiroGteI+QZ09ydHnFng54yE9onnMZG4nRLvGqCf5x9VGLcpciafM2fEeoAU3XJAFvJgLXyrsafocRB/5GGx3DnVa+9jQmMSSHk= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733747901450792.3417230992139; Mon, 9 Dec 2024 04:38:21 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd1B-0003mt-Tt; Mon, 09 Dec 2024 07:37:41 -0500 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 <pbonzini@redhat.com>) id 1tKd12-0003kR-7x for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:35 -0500 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 <pbonzini@redhat.com>) id 1tKd0z-0007Nv-38 for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:31 -0500 Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-396-Qr6IG8QJMyCZ9dfloSjGlQ-1; Mon, 09 Dec 2024 07:37:24 -0500 Received: by mail-wm1-f71.google.com with SMTP id 5b1f17b1804b1-434f0206a83so9544855e9.3 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:37:24 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-434f08b9eebsm74725945e9.10.2024.12.09.04.37.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:37:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747845; 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=EK+6NhPLRnfB+w3ii90rEiEDD8OWs1ZakSYY9qmOsvM=; b=HmX/HCXIZD0Q9/iR3NZzaGbZlDPUMgSNQY5NbGua9teOpPSkq4rnoM5ZL0BfU+UvYLkZv3 ZXZoSHDRGiEC4Cl/8rrYdG+ZLd5HJY70k/8VA1pn1SD1qw3ZO0Mf2dMB0n4JhIQC574WHL AcKsZ1DxYg4S7ICUQYBNKvmBnghBJ6o= X-MC-Unique: Qr6IG8QJMyCZ9dfloSjGlQ-1 X-Mimecast-MFC-AGG-ID: Qr6IG8QJMyCZ9dfloSjGlQ X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747842; x=1734352642; 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=EK+6NhPLRnfB+w3ii90rEiEDD8OWs1ZakSYY9qmOsvM=; b=w9AtqdWe83RKi2ic4Rtz6QpgYBt6A2WuV/UiythWoS4FEXuAj40x0QmAVaIMH9U1lw X7U1Tav0RcbGWB7lxFmTcbYGkzfnbJ4jvMBnsqnYrK8vC9bY5xqDvE3TG+Wv0deucyAW /k5iN5nw3sxge1pV5aJ45UWFW/43cWtzqFt48YW2uXJohIoeBDxvpCZunN6pONJKweC8 XyBWtcpic83F+Nml5aapgIXx6+5rUBfIp54VYB40zfO1LArd8UdjQScEdyqEI28i8SJN LNfPN5vOEY+m9ckvS76XNxzPOlbYUsyYRSnzVqIm01pC4LY/s+Tfwhf3rhEUh1UWFvny a21w== X-Gm-Message-State: AOJu0YyJRgUJ7uOEQYTUdl+gbQN9Ah7lHVNvhI3KKuGshZZPE4jz+EOU J1l6qjgcJ0fA/b+9r0jx3/Sb6IFZpMc4xvBpKG3Axfb/4njK259/8yahTi8iohP8bGV8fTeen+a ZY8SYYifOJK4XSun6t0+fXYGFJ6sXWyevGrDSI5PVS4D17EkQAeN3F24R9mkLK8FGQ30GNnI2LE eWtfKsALIs6yOZH3AoUiDNcNFzKXCoY/SiKDOQ X-Gm-Gg: ASbGnctE21jBH3HH5VUar0y68ltbdz6EMJ/PACl/cg0KQJPGCx17snOgCDVrT3ev61J YRDP7fK8Rn5kHUUu2iU7yfr22VESyOmUFDy+it3T3tn+OIM/zYIodhrwImE5RdQ+7i7fY7Bw2Y4 2c7TTJIdKQxqTFZNIlE7K0dZRmivUl3WVCQCPY/57sKpKudMYaOOcjB0HlqOg1btuvgjAuqSR3s +m+BFJhd+3sFsZFD4Vc2w6TI2HBVbK59LBe5R8lOZLqKAMJq0XXMQ== X-Received: by 2002:a05:600c:4e8a:b0:434:ffd7:6fca with SMTP id 5b1f17b1804b1-434fff36e7cmr2877565e9.2.1733747842557; Mon, 09 Dec 2024 04:37:22 -0800 (PST) X-Google-Smtp-Source: AGHT+IF8GPC6tM8BP4oyS2XcKjZs8CdR5KwXF8EBpX963R9c5kDlndkEeVFU1H/170eovy4nBhnt/A== X-Received: by 2002:a05:600c:4e8a:b0:434:ffd7:6fca with SMTP id 5b1f17b1804b1-434fff36e7cmr2877225e9.2.1733747842143; Mon, 09 Dec 2024 04:37:22 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 01/26] bql: check that the BQL is not dropped within marked sections Date: Mon, 9 Dec 2024 13:36:52 +0100 Message-ID: <20241209123717.99077-2-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=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: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733747902464116600 Content-Type: text/plain; charset="utf-8" The Big QEMU Lock (BQL) is used to provide interior mutability to Rust code. While BqlCell performs indivisible accesses, an equivalent of RefCell will allow the borrower to hold to the interior content for a long time. If the BQL is dropped, another thread could come and mutate the data from C code (Rust code would panic on borrow_mut() instead). In order to prevent this, add a new BQL primitive that can mark BQL-atomic sections and aborts if the BQL is dropped within them. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- include/qemu/main-loop.h | 15 +++++++++++++++ stubs/iothread-lock.c | 15 +++++++++++++++ system/cpus.c | 15 +++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h index 5764db157c9..646306c272f 100644 --- a/include/qemu/main-loop.h +++ b/include/qemu/main-loop.h @@ -262,6 +262,21 @@ AioContext *iohandler_get_aio_context(void); */ bool bql_locked(void); =20 +/** + * bql_block: Allow/deny releasing the BQL + * + * The Big QEMU Lock (BQL) is used to provide interior mutability to + * Rust code, but this only works if other threads cannot run while + * the Rust code has an active borrow. This is because C code in + * other threads could come in and mutate data under the Rust code's + * feet. + * + * @increase: Whether to increase or decrease the blocking counter. + * Releasing the BQL while the counter is nonzero triggers + * an assertion failure. + */ +void bql_block_unlock(bool increase); + /** * qemu_in_main_thread: return whether it's possible to safely access * the global state of the block layer. diff --git a/stubs/iothread-lock.c b/stubs/iothread-lock.c index d7890e5581c..54676598950 100644 --- a/stubs/iothread-lock.c +++ b/stubs/iothread-lock.c @@ -1,6 +1,8 @@ #include "qemu/osdep.h" #include "qemu/main-loop.h" =20 +static uint32_t bql_unlock_blocked; + bool bql_locked(void) { return false; @@ -12,4 +14,17 @@ void bql_lock_impl(const char *file, int line) =20 void bql_unlock(void) { + assert(!bql_unlock_blocked); +} + +void bql_block_unlock(bool increase) +{ + uint32_t new_value; + + assert(bql_locked()); + + /* check for overflow! */ + new_value =3D bql_unlock_blocked + increase - !increase; + assert((new_value > bql_unlock_blocked) =3D=3D increase); + bql_unlock_blocked =3D new_value; } diff --git a/system/cpus.c b/system/cpus.c index 1c818ff6828..ba633c7688b 100644 --- a/system/cpus.c +++ b/system/cpus.c @@ -514,6 +514,20 @@ bool qemu_in_vcpu_thread(void) =20 QEMU_DEFINE_STATIC_CO_TLS(bool, bql_locked) =20 +static uint32_t bql_unlock_blocked; + +void bql_block_unlock(bool increase) +{ + uint32_t new_value; + + assert(bql_locked()); + + /* check for overflow! */ + new_value =3D bql_unlock_blocked + increase - !increase; + assert((new_value > bql_unlock_blocked) =3D=3D increase); + bql_unlock_blocked =3D new_value; +} + bool bql_locked(void) { return get_bql_locked(); @@ -540,6 +554,7 @@ void bql_lock_impl(const char *file, int line) void bql_unlock(void) { g_assert(bql_locked()); + g_assert(!bql_unlock_blocked); set_bql_locked(false); qemu_mutex_unlock(&bql); } --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733747902; cv=none; d=zohomail.com; s=zohoarc; b=FAhnKzqXW5kHR5pKtxs7E3XjBHiLQhd+hrje0IxnFhUd9opz0+8kM1TP10O3MFgcCezYWZuqwwNGvTkA68XkNlLxu+lNvn0Ej7rKa4KckE20jLvIc+KJ8puRiBFKtFarPZ/Ijxkk5O1vKF/DbC0izGYKr5EkeTb0q1sFUoIwxfo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733747902; 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=6JBMRY3yPwvZl5yJZxibeS0bOveitWDH+vkfjHoXH08=; b=R7VUGcIUePoa+Pjrlx0LcibF00rrgI3+lQWFhwWSckbXfFt2k7Y4zsDai0gt/t3xOXFELJNdgpkdqp/TPlQWyEM4s1ostR6G5xiVxcEte47sMDaMaY1TQr8geTb8I8givwhfPTMAeROSUO92yddcl7FGWCFQIjazytVbL50muiY= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733747902594389.66679913150324; Mon, 9 Dec 2024 04:38:22 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd1M-0003rB-Eo; Mon, 09 Dec 2024 07:37:52 -0500 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 <pbonzini@redhat.com>) id 1tKd12-0003kU-Mb for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:36 -0500 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 <pbonzini@redhat.com>) id 1tKd0z-0007OE-Mc for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:32 -0500 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-475-4uZFsdDuMH2IHgw5lryulg-1; Mon, 09 Dec 2024 07:37:27 -0500 Received: by mail-wm1-f69.google.com with SMTP id 5b1f17b1804b1-434f1084293so13101865e9.2 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:37:26 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-434fd4b2898sm15527015e9.19.2024.12.09.04.37.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:37:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747848; 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=6JBMRY3yPwvZl5yJZxibeS0bOveitWDH+vkfjHoXH08=; b=G+P772Mb1tkxwmK+bO2rjGkpVcUdi4gjHx4R3AWSs7fhq530dv8BS/Dv8FCPUaQExC8ICd eI8bSxniz8CKe2aTNidVm6JRwWYJ4EnCKQrVPX729+EbiCGVYsePUF7ZzTCXpHohQluh40 IDR1LIvda4O4qSxvSZ5ssFMdXCjzIDI= X-MC-Unique: 4uZFsdDuMH2IHgw5lryulg-1 X-Mimecast-MFC-AGG-ID: 4uZFsdDuMH2IHgw5lryulg X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747845; x=1734352645; 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=6JBMRY3yPwvZl5yJZxibeS0bOveitWDH+vkfjHoXH08=; b=AtBmBWd0F5mEXamJ1Ncv0BzpKkWeipHLeTAWCzsUEYvI0sz2UEavA2uAoxPpgQ9jHa AeRJYJAwbcSmK0OQNrABUAL2juvc6FFkgVxoIiVfv+GbveTCYDQ2bAn+QQDi0E0vsR37 LXjVddlffKElUlmyhZvoTTKyQDcGPyRj1yI3CDuVAojQ73BwJXOMvRAwNQeGUE8crdQO iPhfbJJR/bA+ZZQS3L1xz+xR0FKpzg8wKBrThdrChMD6lMAyNxxVl+s+5bMgDXmYjJrB ArDgDRsCJDdZB6xhcHGjW7C+WOSV83gkJ0RjbJLwJjWpZKva4KbQRmnVSI/o+071iWfD v5lA== X-Gm-Message-State: AOJu0YyJVkH8mQAq4YVZro6sQHTH5NHnc2XmEWVnp0eZj7sj2o9ISttJ 3YNMvjc9gXsL/RNxBD1ZzDz0JAwq0DIHatNeGcHIG438l4cDpCPEbL8cJ/Zt2YK9k3duo0cD0E7 Bic3ZO+JvuiOWvittZ/eAe91pKdrW36iUuA1/DEhQpLdE/HfEmn5fPTo1xro+rzLV7352fvSme1 j6gpXpV5BT8oHKPTl/7cyTTK7qW4FiBhW+PnXt X-Gm-Gg: ASbGncuiiYdTQ1psSw41YfZtF2AaKAlfwlOR6pnaL5NELxmQbz+rbCSxkLvQbRohWyi 6DPqgnwsbHwHl8qPZBeyvLyfQp3LWI/J3UJyi5Rn11glOofwP5uvqfxr+GmjJkfY+FdE6UnCbbA l4QubqrbY4lhzRUnHeAwZVvfQJpeDCHVIMJbX0LmwpBsNqw04nIuNl7q1kDxnF/M/A8dEpH+XLW RkCH1y4fCxgkD2Lbja9YGktav2FcJg1Clb5gia/J4MOsbRSZk7MQQ== X-Received: by 2002:a05:600c:3caa:b0:434:a781:f5e2 with SMTP id 5b1f17b1804b1-434ddea8dbamr99304565e9.8.1733747845281; Mon, 09 Dec 2024 04:37:25 -0800 (PST) X-Google-Smtp-Source: AGHT+IHD7P6eTFmmIpI7mpAZ6CkKK2SpIze9LrdFgaLkbOhnOODa1ZAaL5/07YUmGruY28ZMerohMw== X-Received: by 2002:a05:600c:3caa:b0:434:a781:f5e2 with SMTP id 5b1f17b1804b1-434ddea8dbamr99304175e9.8.1733747844694; Mon, 09 Dec 2024 04:37:24 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 02/26] rust: cell: add BQL-enforcing Cell variant Date: Mon, 9 Dec 2024 13:36:53 +0100 Message-ID: <20241209123717.99077-3-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=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: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733747904342116600 Content-Type: text/plain; charset="utf-8" QEMU objects usually have their pointer shared with the "outside world" very early in their lifetime, for example when they create their MemoryRegions. Because at this point it is not valid anymore to create a &mut reference to the device, individual parts of the device struct must be made mutable in a controlled manner. QEMU's Big Lock (BQL) effectively turns multi-threaded code into single-threaded code while device code runs, as long as the BQL is not released while the device is borrowed (because C code could sneak in and mutate the device). We can then introduce custom interior mutability primi= tives that are semantically similar to the standard library's (single-threaded) Cell and RefCell, but account for QEMU's threading model. Accessing the "BqlCell" or borrowing the "BqlRefCell" requires proving that the BQL is held, and attempting to access without the BQL is a runtime panic, similar to RefCell's already-borrowed panic. With respect to naming I also considered omitting the "Bql" prefix or moving it to the module, e.g. qemu_api::bql::{Cell, RefCell}. However, this could easily lead to mistakes and confusion; for example rustc could suggest the wrong import, leading to subtle bugs. As a start introduce the an equivalent of Cell. Almost all of the code was taken from Rust's standard library, while removing unstable features and probably-unnecessary functionality that constitute a large of the original code. A lot of what's left is documentation, as well as unit tests in the form of doctests. These are not yet integrated in "make check" but can be run with "cargo test --doc". Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- rust/qemu-api/meson.build | 1 + rust/qemu-api/src/cell.rs | 298 ++++++++++++++++++++++++++++++++++++++ rust/qemu-api/src/lib.rs | 1 + 3 files changed, 300 insertions(+) create mode 100644 rust/qemu-api/src/cell.rs diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build index d719c13f46d..edc21e1a3f8 100644 --- a/rust/qemu-api/meson.build +++ b/rust/qemu-api/meson.build @@ -13,6 +13,7 @@ _qemu_api_rs =3D static_library( [ 'src/lib.rs', 'src/bindings.rs', + 'src/cell.rs', 'src/c_str.rs', 'src/definitions.rs', 'src/device_class.rs', diff --git a/rust/qemu-api/src/cell.rs b/rust/qemu-api/src/cell.rs new file mode 100644 index 00000000000..2e4ea8d590d --- /dev/null +++ b/rust/qemu-api/src/cell.rs @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: MIT +// +// This file is based on library/core/src/cell.rs from +// Rust 1.82.0. +// +// Permission is hereby granted, free of charge, to any +// person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the +// Software without restriction, including without +// limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice +// shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +//! BQL-protected mutable containers. +//! +//! Rust memory safety is based on this rule: Given an object `T`, it is o= nly +//! possible to have one of the following: +//! +//! - Having several immutable references (`&T`) to the object (also known= as +//! **aliasing**). +//! - Having one mutable reference (`&mut T`) to the object (also known as +//! **mutability**). +//! +//! This is enforced by the Rust compiler. However, there are situations w= here +//! this rule is not flexible enough. Sometimes it is required to have mul= tiple +//! references to an object and yet mutate it. In particular, QEMU objects +//! usually have their pointer shared with the "outside world very early in +//! their lifetime", for example when they create their +//! [`MemoryRegion`s](crate::bindings::MemoryRegion). Therefore, individu= al +//! parts of a device must be made mutable in a controlled manner through= the +//! use of cell types. +//! +//! This module provides a way to do so via the Big QEMU Lock. While +//! [`BqlCell<T>`] is essentially the same single-threaded primitive that = is +//! available in `std::cell`, the BQL allows it to be used from a multi-th= readed +//! context and to share references across threads, while maintaining Rust= 's +//! safety guarantees. For this reason, unlike its `std::cell` counterpar= t, +//! `BqlCell` implements the `Sync` trait. +//! +//! BQL checks are performed in debug builds but can be optimized away in +//! release builds, providing runtime safety during development with no ov= erhead +//! in production. +//! +//! Warning: While `BqlCell` is similar to its `std::cell` counterpart, th= e two +//! are not interchangeable. Using `std::cell` types in QEMU device +//! implementations is usually incorrect and can lead to thread-safety iss= ues. +//! +//! ## `BqlCell<T>` +//! +//! [`BqlCell<T>`] implements interior mutability by moving values in and = out of +//! the cell. That is, an `&mut T` to the inner value can never be obtaine= d as +//! long as the cell is shared. The value itself cannot be directly obtain= ed +//! without copying it, cloning it, or replacing it with something else. T= his +//! type provides the following methods, all of which can be called only w= hile +//! the BQL is held: +//! +//! - For types that implement [`Copy`], the [`get`](BqlCell::get) method +//! retrieves the current interior value by duplicating it. +//! - For types that implement [`Default`], the [`take`](BqlCell::take) m= ethod +//! replaces the current interior value with [`Default::default()`] and +//! returns the replaced value. +//! - All types have: +//! - [`replace`](BqlCell::replace): replaces the current interior valu= e and +//! returns the replaced value. +//! - [`set`](BqlCell::set): this method replaces the interior value, +//! dropping the replaced value. + +use std::{cell::UnsafeCell, cmp::Ordering, fmt, mem}; + +use crate::bindings; + +// TODO: When building doctests do not include the actual BQL, because car= go +// does not know how to link them to libqemuutil. This can be fixed by +// running rustdoc from "meson test" instead of relying on cargo. +pub fn bql_locked() -> bool { + // SAFETY: the function does nothing but return a thread-local bool + !cfg!(MESON) || unsafe { bindings::bql_locked() } +} + +/// A mutable memory location that is protected by the Big QEMU Lock. +/// +/// # Memory layout +/// +/// `BqlCell<T>` has the same in-memory representation as its inner type `= T`. +#[repr(transparent)] +pub struct BqlCell<T> { + value: UnsafeCell<T>, +} + +// SAFETY: Same as for std::sync::Mutex. In the end this *is* a Mutex, +// except it is stored out-of-line +unsafe impl<T: Send> Send for BqlCell<T> {} +unsafe impl<T: Send> Sync for BqlCell<T> {} + +impl<T: Copy> Clone for BqlCell<T> { + #[inline] + fn clone(&self) -> BqlCell<T> { + BqlCell::new(self.get()) + } +} + +impl<T: Default> Default for BqlCell<T> { + /// Creates a `BqlCell<T>`, with the `Default` value for T. + #[inline] + fn default() -> BqlCell<T> { + BqlCell::new(Default::default()) + } +} + +impl<T: PartialEq + Copy> PartialEq for BqlCell<T> { + #[inline] + fn eq(&self, other: &BqlCell<T>) -> bool { + self.get() =3D=3D other.get() + } +} + +impl<T: Eq + Copy> Eq for BqlCell<T> {} + +impl<T: PartialOrd + Copy> PartialOrd for BqlCell<T> { + #[inline] + fn partial_cmp(&self, other: &BqlCell<T>) -> Option<Ordering> { + self.get().partial_cmp(&other.get()) + } +} + +impl<T: Ord + Copy> Ord for BqlCell<T> { + #[inline] + fn cmp(&self, other: &BqlCell<T>) -> Ordering { + self.get().cmp(&other.get()) + } +} + +impl<T> From<T> for BqlCell<T> { + /// Creates a new `BqlCell<T>` containing the given value. + fn from(t: T) -> BqlCell<T> { + BqlCell::new(t) + } +} + +impl<T: fmt::Debug + Copy> fmt::Debug for BqlCell<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.get().fmt(f) + } +} + +impl<T: fmt::Display + Copy> fmt::Display for BqlCell<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.get().fmt(f) + } +} + +impl<T> BqlCell<T> { + /// Creates a new `BqlCell` containing the given value. + /// + /// # Examples + /// + /// ``` + /// use qemu_api::cell::BqlCell; + /// + /// let c =3D BqlCell::new(5); + /// ``` + #[inline] + pub const fn new(value: T) -> BqlCell<T> { + BqlCell { + value: UnsafeCell::new(value), + } + } + + /// Sets the contained value. + /// + /// # Examples + /// + /// ``` + /// use qemu_api::cell::BqlCell; + /// + /// let c =3D BqlCell::new(5); + /// + /// c.set(10); + /// ``` + #[inline] + pub fn set(&self, val: T) { + self.replace(val); + } + + /// Replaces the contained value with `val`, and returns the old conta= ined + /// value. + /// + /// # Examples + /// + /// ``` + /// use qemu_api::cell::BqlCell; + /// + /// let cell =3D BqlCell::new(5); + /// assert_eq!(cell.get(), 5); + /// assert_eq!(cell.replace(10), 5); + /// assert_eq!(cell.get(), 10); + /// ``` + #[inline] + pub fn replace(&self, val: T) -> T { + assert!(bql_locked()); + // SAFETY: This can cause data races if called from multiple threa= ds, + // but it won't happen as long as C code accesses the value + // under BQL protection only. + mem::replace(unsafe { &mut *self.value.get() }, val) + } + + /// Unwraps the value, consuming the cell. + /// + /// # Examples + /// + /// ``` + /// use qemu_api::cell::BqlCell; + /// + /// let c =3D BqlCell::new(5); + /// let five =3D c.into_inner(); + /// + /// assert_eq!(five, 5); + /// ``` + pub fn into_inner(self) -> T { + assert!(bql_locked()); + self.value.into_inner() + } +} + +impl<T: Copy> BqlCell<T> { + /// Returns a copy of the contained value. + /// + /// # Examples + /// + /// ``` + /// use qemu_api::cell::BqlCell; + /// + /// let c =3D BqlCell::new(5); + /// + /// let five =3D c.get(); + /// ``` + #[inline] + pub fn get(&self) -> T { + assert!(bql_locked()); + // SAFETY: This can cause data races if called from multiple threa= ds, + // but it won't happen as long as C code accesses the value + // under BQL protection only. + unsafe { *self.value.get() } + } +} + +impl<T> BqlCell<T> { + /// Returns a raw pointer to the underlying data in this cell. + /// + /// # Examples + /// + /// ``` + /// use qemu_api::cell::BqlCell; + /// + /// let c =3D BqlCell::new(5); + /// + /// let ptr =3D c.as_ptr(); + /// ``` + #[inline] + pub const fn as_ptr(&self) -> *mut T { + self.value.get() + } +} + +impl<T: Default> BqlCell<T> { + /// Takes the value of the cell, leaving `Default::default()` in its p= lace. + /// + /// # Examples + /// + /// ``` + /// use qemu_api::cell::BqlCell; + /// + /// let c =3D BqlCell::new(5); + /// let five =3D c.take(); + /// + /// assert_eq!(five, 5); + /// assert_eq!(c.into_inner(), 0); + /// ``` + pub fn take(&self) -> T { + self.replace(Default::default()) + } +} diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs index 440aff3817d..b04d110b3f5 100644 --- a/rust/qemu-api/src/lib.rs +++ b/rust/qemu-api/src/lib.rs @@ -8,6 +8,7 @@ pub mod bindings; =20 pub mod c_str; +pub mod cell; pub mod definitions; pub mod device_class; pub mod offset_of; --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733747912; cv=none; d=zohomail.com; s=zohoarc; b=FmwqR+R7kM8mWtW3Z50zfslLE4Z316ahD8iggvycYRoyOIIuSzcxAVnRfczdJzs1cqCxM8FotMrOuQWHxNHLLLv9VEy7jeVhK4WJkbg9fFlL6vPlCJw78sEoA119CapP1xXwC5IgdRabUi6SHE+PtuuEM8d2jc0y+bA1b8ZBuxM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733747912; 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=wMF7KkhAi7BwGkG3WdZkbBzWjurjR2HS0qfiOPgjOHU=; b=C1hkIKqohuRcWd8fXfpTWPeW1759v74ixLPks0gsffD7mDNfBQnFghiH/wLgI5K/Dg7Hb3r4rZ8n7STX78QPJuDE56V0g2SEWzQABV80WIFZDLEznjzMVn9JRi9Rsk2OtzVdnZQIXpuRoKmdBu6QNNpJN35RFngWhMd/n1XJG5g= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733747912874590.1410596188917; Mon, 9 Dec 2024 04:38:32 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd1H-0003ou-DH; Mon, 09 Dec 2024 07:37:48 -0500 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 <pbonzini@redhat.com>) id 1tKd15-0003kY-Ao for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:36 -0500 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 <pbonzini@redhat.com>) id 1tKd12-0007Os-Ky for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:34 -0500 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-689-pQFKVHTeOvCIz2ifL1kGZw-1; Mon, 09 Dec 2024 07:37:30 -0500 Received: by mail-wr1-f69.google.com with SMTP id ffacd0b85a97d-386333ea577so759322f8f.1 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:37:30 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-386348182d4sm7824324f8f.53.2024.12.09.04.37.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:37:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747851; 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=wMF7KkhAi7BwGkG3WdZkbBzWjurjR2HS0qfiOPgjOHU=; b=h8pMut6dg+8ZRrehkM/PM2FXRIqf/0A/kyBZfZ0UQSB4MR6ZzSqRn+yWEsUMAXSCFHeYyS qZYv0XKoWcZO6t89aQWaiSNytNdvNAoORasJD4L2rY/NKbkLatXJ8LZw+ra0CkqQ0XwxXl FSnj8/f+ICMvu8VaCoulX57Hmdf/ymU= X-MC-Unique: pQFKVHTeOvCIz2ifL1kGZw-1 X-Mimecast-MFC-AGG-ID: pQFKVHTeOvCIz2ifL1kGZw X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747848; x=1734352648; 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=wMF7KkhAi7BwGkG3WdZkbBzWjurjR2HS0qfiOPgjOHU=; b=LsBlaEVJzVrUENmC9ig12kkk8Ep+C5puydqbttXN3e9WklpGRnCfO6nBK8PraD94ZS ptMbqmMsOuOABEsJKO/uSaOm65spsgU3efUDDcz2p/GZDgJ2t2cKM7jQWQkPz1ZBRtcG w+kbR2CeHTYZmbwYPsZu9EJFj26dRm2EJnqgk//4tg260sdRr3mI4XpAzU2udR63ke7W 6CdmfptFCvOzibhmO9g5onT9Pga/Vn9a1C7Eq4zdv1o0DEAuszxZoH4S3B1AxwOsUau4 YwivwbsAN0n+bslCrnGZb3+v73jjI+kC7XdF3Nq/oG9CwOWdKYlgG7BrbQktrCJYjeFR JN0A== X-Gm-Message-State: AOJu0YzqeZWLjIqrZ7Sm2KJ/QcNxXjkl7ZW+Edu5398kXlcAJ9TM2M5l Z2mZD8/9s+PL9gH4175VVB6n9dtHo5SSqXF+pbw+ImJycibklciEOtgQUrPlqWwD+fH53oJVUpv O4q8IKApijoC4D3Td/QzPpGzVD+O4dxZfNHiIbiFzZmfiDNSrWAseD/Yef3hdsXgcs1WRsLAHsL brGvdV94Bztyvonv9ZehNJl3sm8Madvupp+axD X-Gm-Gg: ASbGncuqEdEjzEbe/JSHZfGf10H6hsS51BX9kQyTNCdv2xFnBEP6kaTO6c+hFHlRB1v jYwC/xidGEUey2K9iHeafi1CUWi7YQB7EjaMTntbcd2nvSdjgYWsYIrVg8ZE7KU3xTLoAZlN6k0 GNt3ghLj201KK/Y3GPKTKQe6P2WC1B/NedqkNJfm/ulAMBO8+Th6/nSIYLGzAq90V5uOe72p68u kZOVQ4fJ/PVhwrD39SnqIbbrJnS0RrV/Y6q7eZPdspUUMEGLafp2A== X-Received: by 2002:a5d:5f53:0:b0:386:5b2:a9d9 with SMTP id ffacd0b85a97d-386453fbd04mr134476f8f.53.1733747847960; Mon, 09 Dec 2024 04:37:27 -0800 (PST) X-Google-Smtp-Source: AGHT+IHudZUgpkRU+aSyObe3pCtfO2GlnG4ukBn4FRXPkvB8Xz3AG0t9lU7v4GCtsSs9xEN66yW4yw== X-Received: by 2002:a5d:5f53:0:b0:386:5b2:a9d9 with SMTP id ffacd0b85a97d-386453fbd04mr134437f8f.53.1733747847279; Mon, 09 Dec 2024 04:37:27 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 03/26] rust: cell: add BQL-enforcing RefCell variant Date: Mon, 9 Dec 2024 13:36:54 +0100 Message-ID: <20241209123717.99077-4-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=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: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733747914200116600 Content-Type: text/plain; charset="utf-8" Similar to the existing BqlCell, introduce a custom interior mutability primitive that resembles RefCell but accounts for QEMU's threading model. Borrowing the RefCell requires proving that the BQL is held, and attempting to access without the BQL is a runtime panic. Almost all of the code was taken from Rust's standard library, while removing unstable features and probably-unnecessary functionality that amounts to 60% of the original code. A lot of what's left is documentation, as well as unit tests in the form of doctests. These are not yet integrated in "make check" but can be run with "cargo test --doc". Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- rust/qemu-api/Cargo.toml | 3 +- rust/qemu-api/meson.build | 3 + rust/qemu-api/src/cell.rs | 544 +++++++++++++++++++++++++++++++++++++- 3 files changed, 539 insertions(+), 11 deletions(-) diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml index 669f288d1cb..4aa22f31986 100644 --- a/rust/qemu-api/Cargo.toml +++ b/rust/qemu-api/Cargo.toml @@ -20,8 +20,9 @@ qemu_api_macros =3D { path =3D "../qemu-api-macros" } version_check =3D "~0.9" =20 [features] -default =3D [] +default =3D ["debug_cell"] allocator =3D [] +debug_cell =3D [] =20 [lints] workspace =3D true diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build index edc21e1a3f8..cacb112c5c3 100644 --- a/rust/qemu-api/meson.build +++ b/rust/qemu-api/meson.build @@ -6,6 +6,9 @@ _qemu_api_cfg =3D run_command(rustc_args, if rustc.version().version_compare('>=3D1.77.0') _qemu_api_cfg +=3D ['--cfg', 'has_offset_of'] endif +if get_option('debug_mutex') + _qemu_api_cfg +=3D ['--feature', 'debug_cell'] +endif =20 _qemu_api_rs =3D static_library( 'qemu_api', diff --git a/rust/qemu-api/src/cell.rs b/rust/qemu-api/src/cell.rs index 2e4ea8d590d..28349de291a 100644 --- a/rust/qemu-api/src/cell.rs +++ b/rust/qemu-api/src/cell.rs @@ -46,20 +46,30 @@ //! parts of a device must be made mutable in a controlled manner through= the //! use of cell types. //! -//! This module provides a way to do so via the Big QEMU Lock. While -//! [`BqlCell<T>`] is essentially the same single-threaded primitive that = is -//! available in `std::cell`, the BQL allows it to be used from a multi-th= readed -//! context and to share references across threads, while maintaining Rust= 's -//! safety guarantees. For this reason, unlike its `std::cell` counterpar= t, -//! `BqlCell` implements the `Sync` trait. +//! [`BqlCell<T>`] and [`BqlRefCell<T>`] allow doing this via the Big QEMU= Lock. +//! While they are essentially the same single-threaded primitives that are +//! available in `std::cell`, the BQL allows them to be used from a +//! multi-threaded context and to share references across threads, while +//! maintaining Rust's safety guarantees. For this reason, unlike +//! their `std::cell` counterparts, `BqlCell` and `BqlRefCell` implement t= he +//! `Sync` trait. //! //! BQL checks are performed in debug builds but can be optimized away in //! release builds, providing runtime safety during development with no ov= erhead //! in production. //! -//! Warning: While `BqlCell` is similar to its `std::cell` counterpart, th= e two -//! are not interchangeable. Using `std::cell` types in QEMU device -//! implementations is usually incorrect and can lead to thread-safety iss= ues. +//! The two provide different ways of handling interior mutability. +//! `BqlRefCell` is best suited for data that is primarily accessed by the +//! device's own methods, where multiple reads and writes can be grouped w= ithin +//! a single borrow and a mutable reference can be passed around. Instead, +//! [`BqlCell`] is a better choice when sharing small pieces of data with +//! external code (especially C code), because it provides simple get/set +//! operations that can be used one at a time. +//! +//! Warning: While `BqlCell` and `BqlRefCell` are similar to their `std::c= ell` +//! counterparts, they are not interchangeable. Using `std::cell` types in +//! QEMU device implementations is usually incorrect and can lead to +//! thread-safety issues. //! //! ## `BqlCell<T>` //! @@ -80,8 +90,37 @@ //! returns the replaced value. //! - [`set`](BqlCell::set): this method replaces the interior value, //! dropping the replaced value. +//! +//! ## `BqlRefCell<T>` +//! +//! [`BqlRefCell<T>`] uses Rust's lifetimes to implement "dynamic borrowin= g", a +//! process whereby one can claim temporary, exclusive, mutable access to = the +//! inner value: +//! +//! ```ignore +//! fn clear_interrupts(&self, val: u32) { +//! // A mutable borrow gives read-write access to the registers +//! let mut regs =3D self.registers.borrow_mut(); +//! let old =3D regs.interrupt_status(); +//! regs.update_interrupt_status(old & !val); +//! } +//! ``` +//! +//! Borrows for `BqlRefCell<T>`s are tracked at _runtime_, unlike Rust's n= ative +//! reference types which are entirely tracked statically, at compile time. +//! Multiple immutable borrows are allowed via [`borrow`](BqlRefCell::borr= ow), +//! or a single mutable borrow via [`borrow_mut`](BqlRefCell::borrow_mut).= The +//! thread will panic if these rules are violated or if the BQL is not hel= d. =20 -use std::{cell::UnsafeCell, cmp::Ordering, fmt, mem}; +use std::{ + cell::{Cell, UnsafeCell}, + cmp::Ordering, + fmt, + marker::PhantomData, + mem, + ops::{Deref, DerefMut}, + ptr::NonNull, +}; =20 use crate::bindings; =20 @@ -93,6 +132,15 @@ pub fn bql_locked() -> bool { !cfg!(MESON) || unsafe { bindings::bql_locked() } } =20 +fn bql_block_unlock(increase: bool) { + if cfg!(MESON) { + // SAFETY: this only adjusts a counter + unsafe { + bindings::bql_block_unlock(increase); + } + } +} + /// A mutable memory location that is protected by the Big QEMU Lock. /// /// # Memory layout @@ -296,3 +344,479 @@ pub fn take(&self) -> T { self.replace(Default::default()) } } + +/// A mutable memory location with dynamically checked borrow rules, +/// protected by the Big QEMU Lock. +/// +/// See the [module-level documentation](self) for more. +/// +/// # Memory layout +/// +/// `BqlRefCell<T>` starts with the same in-memory representation as its +/// inner type `T`. +#[repr(C)] +pub struct BqlRefCell<T> { + // It is important that this is the first field (which is not the case + // for std::cell::BqlRefCell), so that we can use offset_of! on it. + // UnsafeCell and repr(C) both prevent usage of niches. + value: UnsafeCell<T>, + borrow: Cell<BorrowFlag>, + // Stores the location of the earliest currently active borrow. + // This gets updated whenever we go from having zero borrows + // to having a single borrow. When a borrow occurs, this gets included + // in the panic message + #[cfg(feature =3D "debug_cell")] + borrowed_at: Cell<Option<&'static std::panic::Location<'static>>>, +} + +// Positive values represent the number of `BqlRef` active. Negative values +// represent the number of `BqlRefMut` active. Right now QEMU's implementa= tion +// does not allow to create `BqlRefMut`s that refer to distinct, nonoverla= pping +// components of a `BqlRefCell` (e.g., different ranges of a slice). +// +// `BqlRef` and `BqlRefMut` are both two words in size, and so there will = likely +// never be enough `BqlRef`s or `BqlRefMut`s in existence to overflow half= of +// the `usize` range. Thus, a `BorrowFlag` will probably never overflow or +// underflow. However, this is not a guarantee, as a pathological program = could +// repeatedly create and then mem::forget `BqlRef`s or `BqlRefMut`s. Thus,= all +// code must explicitly check for overflow and underflow in order to avoid +// unsafety, or at least behave correctly in the event that overflow or +// underflow happens (e.g., see BorrowRef::new). +type BorrowFlag =3D isize; +const UNUSED: BorrowFlag =3D 0; + +#[inline(always)] +const fn is_writing(x: BorrowFlag) -> bool { + x < UNUSED +} + +#[inline(always)] +const fn is_reading(x: BorrowFlag) -> bool { + x > UNUSED +} + +impl<T> BqlRefCell<T> { + /// Creates a new `BqlRefCell` containing `value`. + /// + /// # Examples + /// + /// ``` + /// use qemu_api::cell::BqlRefCell; + /// + /// let c =3D BqlRefCell::new(5); + /// ``` + #[inline] + pub const fn new(value: T) -> BqlRefCell<T> { + BqlRefCell { + value: UnsafeCell::new(value), + borrow: Cell::new(UNUSED), + #[cfg(feature =3D "debug_cell")] + borrowed_at: Cell::new(None), + } + } +} + +// This ensures the panicking code is outlined from `borrow_mut` for +// `BqlRefCell`. +#[inline(never)] +#[cold] +#[cfg(feature =3D "debug_cell")] +fn panic_already_borrowed(source: &Cell<Option<&'static std::panic::Locati= on<'static>>>) -> ! { + // If a borrow occurred, then we must already have an outstanding borr= ow, + // so `borrowed_at` will be `Some` + panic!("already borrowed at {:?}", source.take().unwrap()) +} + +#[inline(never)] +#[cold] +#[cfg(not(feature =3D "debug_cell"))] +fn panic_already_borrowed() -> ! { + panic!("already borrowed") +} + +impl<T> BqlRefCell<T> { + #[inline] + #[allow(clippy::unused_self)] + fn panic_already_borrowed(&self) -> ! { + #[cfg(feature =3D "debug_cell")] + { + panic_already_borrowed(&self.borrowed_at) + } + #[cfg(not(feature =3D "debug_cell"))] + { + panic_already_borrowed() + } + } + + /// Immutably borrows the wrapped value. + /// + /// The borrow lasts until the returned `BqlRef` exits scope. Multiple + /// immutable borrows can be taken out at the same time. + /// + /// # Panics + /// + /// Panics if the value is currently mutably borrowed. + /// + /// # Examples + /// + /// ``` + /// use qemu_api::cell::BqlRefCell; + /// + /// let c =3D BqlRefCell::new(5); + /// + /// let borrowed_five =3D c.borrow(); + /// let borrowed_five2 =3D c.borrow(); + /// ``` + /// + /// An example of panic: + /// + /// ```should_panic + /// use qemu_api::cell::BqlRefCell; + /// + /// let c =3D BqlRefCell::new(5); + /// + /// let m =3D c.borrow_mut(); + /// let b =3D c.borrow(); // this causes a panic + /// ``` + #[inline] + #[track_caller] + pub fn borrow(&self) -> BqlRef<'_, T> { + if let Some(b) =3D BorrowRef::new(&self.borrow) { + // `borrowed_at` is always the *first* active borrow + if b.borrow.get() =3D=3D 1 { + #[cfg(feature =3D "debug_cell")] + self.borrowed_at.set(Some(std::panic::Location::caller())); + } + + bql_block_unlock(true); + + // SAFETY: `BorrowRef` ensures that there is only immutable ac= cess + // to the value while borrowed. + let value =3D unsafe { NonNull::new_unchecked(self.value.get()= ) }; + BqlRef { value, borrow: b } + } else { + self.panic_already_borrowed() + } + } + + /// Mutably borrows the wrapped value. + /// + /// The borrow lasts until the returned `BqlRefMut` or all `BqlRefMut`s + /// derived from it exit scope. The value cannot be borrowed while this + /// borrow is active. + /// + /// # Panics + /// + /// Panics if the value is currently borrowed. + /// + /// # Examples + /// + /// ``` + /// use qemu_api::cell::BqlRefCell; + /// + /// let c =3D BqlRefCell::new("hello".to_owned()); + /// + /// *c.borrow_mut() =3D "bonjour".to_owned(); + /// + /// assert_eq!(&*c.borrow(), "bonjour"); + /// ``` + /// + /// An example of panic: + /// + /// ```should_panic + /// use qemu_api::cell::BqlRefCell; + /// + /// let c =3D BqlRefCell::new(5); + /// let m =3D c.borrow(); + /// + /// let b =3D c.borrow_mut(); // this causes a panic + /// ``` + #[inline] + #[track_caller] + pub fn borrow_mut(&self) -> BqlRefMut<'_, T> { + if let Some(b) =3D BorrowRefMut::new(&self.borrow) { + #[cfg(feature =3D "debug_cell")] + { + self.borrowed_at.set(Some(std::panic::Location::caller())); + } + + // SAFETY: this only adjusts a counter + bql_block_unlock(true); + + // SAFETY: `BorrowRefMut` guarantees unique access. + let value =3D unsafe { NonNull::new_unchecked(self.value.get()= ) }; + BqlRefMut { + value, + _borrow: b, + marker: PhantomData, + } + } else { + self.panic_already_borrowed() + } + } + + /// Returns a raw pointer to the underlying data in this cell. + /// + /// # Examples + /// + /// ``` + /// use qemu_api::cell::BqlRefCell; + /// + /// let c =3D BqlRefCell::new(5); + /// + /// let ptr =3D c.as_ptr(); + /// ``` + #[inline] + pub const fn as_ptr(&self) -> *mut T { + self.value.get() + } +} + +// SAFETY: Same as for std::sync::Mutex. In the end this is a Mutex that = is +// stored out-of-line. Even though BqlRefCell includes Cells, they are +// themselves protected by the Big QEMU Lock. Furtheremore, the Big QEMU +// Lock cannot be released while any borrows is active. +unsafe impl<T> Send for BqlRefCell<T> where T: Send {} +unsafe impl<T> Sync for BqlRefCell<T> {} + +impl<T: Clone> Clone for BqlRefCell<T> { + /// # Panics + /// + /// Panics if the value is currently mutably borrowed. + #[inline] + #[track_caller] + fn clone(&self) -> BqlRefCell<T> { + BqlRefCell::new(self.borrow().clone()) + } + + /// # Panics + /// + /// Panics if `source` is currently mutably borrowed. + #[inline] + #[track_caller] + fn clone_from(&mut self, source: &Self) { + self.value.get_mut().clone_from(&source.borrow()) + } +} + +impl<T: Default> Default for BqlRefCell<T> { + /// Creates a `BqlRefCell<T>`, with the `Default` value for T. + #[inline] + fn default() -> BqlRefCell<T> { + BqlRefCell::new(Default::default()) + } +} + +impl<T: PartialEq> PartialEq for BqlRefCell<T> { + /// # Panics + /// + /// Panics if the value in either `BqlRefCell` is currently mutably + /// borrowed. + #[inline] + fn eq(&self, other: &BqlRefCell<T>) -> bool { + *self.borrow() =3D=3D *other.borrow() + } +} + +impl<T: Eq> Eq for BqlRefCell<T> {} + +impl<T: PartialOrd> PartialOrd for BqlRefCell<T> { + /// # Panics + /// + /// Panics if the value in either `BqlRefCell` is currently mutably + /// borrowed. + #[inline] + fn partial_cmp(&self, other: &BqlRefCell<T>) -> Option<Ordering> { + self.borrow().partial_cmp(&*other.borrow()) + } +} + +impl<T: Ord> Ord for BqlRefCell<T> { + /// # Panics + /// + /// Panics if the value in either `BqlRefCell` is currently mutably + /// borrowed. + #[inline] + fn cmp(&self, other: &BqlRefCell<T>) -> Ordering { + self.borrow().cmp(&*other.borrow()) + } +} + +impl<T> From<T> for BqlRefCell<T> { + /// Creates a new `BqlRefCell<T>` containing the given value. + fn from(t: T) -> BqlRefCell<T> { + BqlRefCell::new(t) + } +} + +struct BorrowRef<'b> { + borrow: &'b Cell<BorrowFlag>, +} + +impl<'b> BorrowRef<'b> { + #[inline] + fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRef<'b>> { + let b =3D borrow.get().wrapping_add(1); + if !is_reading(b) { + // Incrementing borrow can result in a non-reading value (<=3D= 0) in these cases: + // 1. It was < 0, i.e. there are writing borrows, so we can't = allow a read + // borrow due to Rust's reference aliasing rules + // 2. It was isize::MAX (the max amount of reading borrows) an= d it overflowed + // into isize::MIN (the max amount of writing borrows) so w= e can't allow an + // additional read borrow because isize can't represent so = many read borrows + // (this can only happen if you mem::forget more than a sma= ll constant amount + // of `BqlRef`s, which is not good practice) + None + } else { + // Incrementing borrow can result in a reading value (> 0) in = these cases: + // 1. It was =3D 0, i.e. it wasn't borrowed, and we are taking= the first read + // borrow + // 2. It was > 0 and < isize::MAX, i.e. there were read borrow= s, and isize is + // large enough to represent having one more read borrow + borrow.set(b); + Some(BorrowRef { borrow }) + } + } +} + +impl Drop for BorrowRef<'_> { + #[inline] + fn drop(&mut self) { + let borrow =3D self.borrow.get(); + debug_assert!(is_reading(borrow)); + self.borrow.set(borrow - 1); + bql_block_unlock(false) + } +} + +impl Clone for BorrowRef<'_> { + #[inline] + fn clone(&self) -> Self { + BorrowRef::new(self.borrow).unwrap() + } +} + +/// Wraps a borrowed reference to a value in a `BqlRefCell` box. +/// A wrapper type for an immutably borrowed value from a `BqlRefCell<T>`. +/// +/// See the [module-level documentation](self) for more. +pub struct BqlRef<'b, T: 'b> { + // NB: we use a pointer instead of `&'b T` to avoid `noalias` violatio= ns, because a + // `BqlRef` argument doesn't hold immutability for its whole scope, on= ly until it drops. + // `NonNull` is also covariant over `T`, just like we would have with = `&T`. + value: NonNull<T>, + borrow: BorrowRef<'b>, +} + +impl<T> Deref for BqlRef<'_, T> { + type Target =3D T; + + #[inline] + fn deref(&self) -> &T { + // SAFETY: the value is accessible as long as we hold our borrow. + unsafe { self.value.as_ref() } + } +} + +impl<'b, T> BqlRef<'b, T> { + /// Copies a `BqlRef`. + /// + /// The `BqlRefCell` is already immutably borrowed, so this cannot fai= l. + /// + /// This is an associated function that needs to be used as + /// `BqlRef::clone(...)`. A `Clone` implementation or a method would + /// interfere with the widespread use of `r.borrow().clone()` to clone + /// the contents of a `BqlRefCell`. + #[must_use] + #[inline] + #[allow(clippy::should_implement_trait)] + pub fn clone(orig: &BqlRef<'b, T>) -> BqlRef<'b, T> { + BqlRef { + value: orig.value, + borrow: orig.borrow.clone(), + } + } +} + +impl<T: fmt::Debug> fmt::Debug for BqlRef<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + +impl<T: fmt::Display> fmt::Display for BqlRef<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + +struct BorrowRefMut<'b> { + borrow: &'b Cell<BorrowFlag>, +} + +impl<'b> BorrowRefMut<'b> { + #[inline] + fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRefMut<'b>> { + // There must currently be no existing references when borrow_mut(= ) is + // called, so we explicitly only allow going from UNUSED to UNUSED= - 1. + match borrow.get() { + UNUSED =3D> { + borrow.set(UNUSED - 1); + Some(BorrowRefMut { borrow }) + } + _ =3D> None, + } + } +} + +impl Drop for BorrowRefMut<'_> { + #[inline] + fn drop(&mut self) { + let borrow =3D self.borrow.get(); + debug_assert!(is_writing(borrow)); + self.borrow.set(borrow + 1); + bql_block_unlock(false) + } +} + +/// A wrapper type for a mutably borrowed value from a `BqlRefCell<T>`. +/// +/// See the [module-level documentation](self) for more. +pub struct BqlRefMut<'b, T: 'b> { + // NB: we use a pointer instead of `&'b mut T` to avoid `noalias` viol= ations, because a + // `BqlRefMut` argument doesn't hold exclusivity for its whole scope, = only until it drops. + value: NonNull<T>, + _borrow: BorrowRefMut<'b>, + // `NonNull` is covariant over `T`, so we need to reintroduce invarian= ce. + marker: PhantomData<&'b mut T>, +} + +impl<T> Deref for BqlRefMut<'_, T> { + type Target =3D T; + + #[inline] + fn deref(&self) -> &T { + // SAFETY: the value is accessible as long as we hold our borrow. + unsafe { self.value.as_ref() } + } +} + +impl<T> DerefMut for BqlRefMut<'_, T> { + #[inline] + fn deref_mut(&mut self) -> &mut T { + // SAFETY: the value is accessible as long as we hold our borrow. + unsafe { self.value.as_mut() } + } +} + +impl<T: fmt::Debug> fmt::Debug for BqlRefMut<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + +impl<T: fmt::Display> fmt::Display for BqlRefMut<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733747958; cv=none; d=zohomail.com; s=zohoarc; b=ffmWtcZZ21G8UNAyj3eDmf9NpWnJdaUf27/LSZCDqRo2Mzx2x0lAn5CKcXEJIp2vDORjiopSLodSaKTGkikucQnWGb5DywT5ilSZPmuuBbNGudMnR/wHfwJA3592FdlsmcMQBvIS08c87TjP0fwqIyXIE4RFTNj2++A4hHTbS2I= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733747958; 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=OshVopfsDLXhXQaf0FN9QUClgxDd1xn/z3ig2ZaD5Nc=; b=OzXBhoJ5Bzvz+rA8UhpIrjTvF100dD96S2ha1i38aGZOQv5bpWILn80kXn5PzrWLGlwepHgMaSI3X94raHEORZULgZtYf8pf6gvxAcuAj4VjTyty4DUjtX3zDaCjFGZcO7rgJvdW5CW4jltm7aAYnGKKqqfD+G968IAwKb5ZqeU= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733747958374442.7617645367649; Mon, 9 Dec 2024 04:39:18 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd1P-0003wU-MX; Mon, 09 Dec 2024 07:37:56 -0500 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 <pbonzini@redhat.com>) id 1tKd1D-0003pF-1K for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:47 -0500 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 <pbonzini@redhat.com>) id 1tKd14-0007P9-Pa for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:38 -0500 Received: from mail-wm1-f70.google.com (mail-wm1-f70.google.com [209.85.128.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-59-RM2fGMT2OO62Mclv16jX4g-1; Mon, 09 Dec 2024 07:37:31 -0500 Received: by mail-wm1-f70.google.com with SMTP id 5b1f17b1804b1-434f387f346so10668025e9.1 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:37:31 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-434ea285b57sm82152305e9.37.2024.12.09.04.37.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:37:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747853; 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=OshVopfsDLXhXQaf0FN9QUClgxDd1xn/z3ig2ZaD5Nc=; b=Nb4sq82fOIiXHRVvS8H9y0NAeucUJlX9eXXVqH1aBKieVqW0LJ6ztvPFcZs2EQR8rbvHqg rclXKkQlW0xQkHpJz1KxQbWlJ8ih8ranQ5qM3gCUdpL29W20WgxfiHE0V/zi7Xt4GYpz5F TUjddMLNuIaAKKisOQW8lZddZGRRSV0= X-MC-Unique: RM2fGMT2OO62Mclv16jX4g-1 X-Mimecast-MFC-AGG-ID: RM2fGMT2OO62Mclv16jX4g X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747849; x=1734352649; 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=OshVopfsDLXhXQaf0FN9QUClgxDd1xn/z3ig2ZaD5Nc=; b=Jbhw4TbJSJQgMJe6pdx3WGabpDNGp2DwZBfFVZdAKG9raI1Qct3lMoGQmZ/a+aDpqg AazKlQrscNLZXcWKdL+Db+3NQ0hM/rFZqtlSLq1BigV3srIgWEOaZqVli+Rt5Y2ATkoo CnHKtEExmzCsAyeJQ2SjOD0BV5FmcCgm/r1uYEECT9YZIFByP29jNOcYdH7X09Y9wAAB P52RQmzjDvlhO9WrLc3RahIK53QnsLJZ8vJPUhjK7XSxwZhL7/3yjObg4UE+MheI/X6B J/D3Z98ba6wKYyUklcavbPzdjbFeXrBN+Hwr0VdEKbT1GhRVGdkfvw207QILJ6IeVRBc F9Ag== X-Gm-Message-State: AOJu0Yymr0ffC14QXKpp7T+oehTV0OVkukrTk3BHVT2V426VKkjUWcAd rgMOpSQZxjyL9mSvIAp5tEY63SyuHfczt48a2pvBrOB8w1aWzM+o7P260UCY76pfbLwJB+Ori96 ma14gkomEjIL7kubE7e5zoiCw9HJ9sbWT0D1VHp7WfH/r+6QMRAOplhdxb8r7dwoGLgZeGH36Wt gp6zrLV157/MzfsUEg3UITFs8lgSRDe21g7IuI X-Gm-Gg: ASbGnctG9GZzW4hhHxlZN610pLHo+Mx4fSHPBH3/emLaZjyqAYxZWMJoFKLfw5INnG/ cIw09lsp/Z82C9ifAYa2B1lZE2Z3VYeW4YtLAVrvPvCAGfnWS5UOYr98w2Y3oYdUaufZc5OXt7f SBLVJzLh4lpgntOUd40O2rv3cV8wsYcRrF6nuJtIxo9Ew09/FMtsfoReUB3Ju9x3nh4BTTzyjW4 y2uW7GPFQk2EI4L/2aco/aTIpprYZ0lz5uhFrjO2zDb3g5+vfD6zg== X-Received: by 2002:a05:600c:218b:b0:434:e8cf:6390 with SMTP id 5b1f17b1804b1-434e8cf6549mr58800695e9.6.1733747849204; Mon, 09 Dec 2024 04:37:29 -0800 (PST) X-Google-Smtp-Source: AGHT+IFHlEgkoznpcJBVMGo3GWGVCxSEwTQXhhE5t4h73rLaMp1i9fY4c8mflKhLCQexfBFrkVKgTQ== X-Received: by 2002:a05:600c:218b:b0:434:e8cf:6390 with SMTP id 5b1f17b1804b1-434e8cf6549mr58800475e9.6.1733747848846; Mon, 09 Dec 2024 04:37:28 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 04/26] rust: define prelude Date: Mon, 9 Dec 2024 13:36:55 +0100 Message-ID: <20241209123717.99077-5-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733747960067116600 Content-Type: text/plain; charset="utf-8" Add a module that will contain frequently used traits and occasionally structs. They can be included quickly with "use qemu_api::prelude::*". Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Zhao Liu <zhao1.liu@intel.com> --- rust/qemu-api/meson.build | 1 + rust/qemu-api/src/lib.rs | 5 +++++ rust/qemu-api/src/prelude.rs | 6 ++++++ 3 files changed, 12 insertions(+) create mode 100644 rust/qemu-api/src/prelude.rs diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build index cacb112c5c3..f8b4cd39a26 100644 --- a/rust/qemu-api/meson.build +++ b/rust/qemu-api/meson.build @@ -21,6 +21,7 @@ _qemu_api_rs =3D static_library( 'src/definitions.rs', 'src/device_class.rs', 'src/offset_of.rs', + 'src/prelude.rs', 'src/vmstate.rs', 'src/zeroable.rs', ], diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs index b04d110b3f5..e5956cd5eb6 100644 --- a/rust/qemu-api/src/lib.rs +++ b/rust/qemu-api/src/lib.rs @@ -7,6 +7,11 @@ #[rustfmt::skip] pub mod bindings; =20 +// preserve one-item-per-"use" syntax, it is clearer +// for prelude-like modules +#[rustfmt::skip] +pub mod prelude; + pub mod c_str; pub mod cell; pub mod definitions; diff --git a/rust/qemu-api/src/prelude.rs b/rust/qemu-api/src/prelude.rs new file mode 100644 index 00000000000..dfaddbd062a --- /dev/null +++ b/rust/qemu-api/src/prelude.rs @@ -0,0 +1,6 @@ +// Copyright 2024 Red Hat, Inc. +// Author(s): Paolo Bonzini <pbonzini@redhat.com> +// SPDX-License-Identifier: GPL-2.0-or-later + +pub use crate::cell::BqlCell; +pub use crate::cell::BqlRefCell; --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733748078; cv=none; d=zohomail.com; s=zohoarc; b=YaWHvqoPW8HIl1CqRD/FVHbyQFl+rYljRyA6TTSqvz+eN+nIuS3ck4yMTR8//ls8NP1jvDiqGFMjbenfuHKnqF+RdrOAp77uOiS/D2RbNu58LoV+UJutC/17NhS4GdSDqhMyJ7k7xH5hpGtXB9mY4eI7hBxUHtXFz5bQQ92ZpDI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733748078; 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=kMi4xnuVX8OtBt4NvX2Y5ZrPSheVzAeHna9cNK+HRcg=; b=FVHV0PiyMbcFRj23AtbTIZqupTjuNKXIuoXkHCwWJjB3skNbqj6LoaR2QM0ZHZMhkqPgQPZJu/vJwwumqfLlJvlanhmgC0bqsTjQDo79JvdEYoMp9D7fqxT8tXlB3QwN3+h9FZSGE+0ZYXyN77tOpYT/mUmrxHQ3+7qzEA3htLs= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733748077972647.1933381732191; Mon, 9 Dec 2024 04:41:17 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd1V-00041A-Lf; Mon, 09 Dec 2024 07:38:01 -0500 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 <pbonzini@redhat.com>) id 1tKd1M-0003rx-Jw for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:52 -0500 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 <pbonzini@redhat.com>) id 1tKd19-0007PX-RP for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:46 -0500 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-155-PEGnbFAANT2A19hQSXB9UQ-1; Mon, 09 Dec 2024 07:37:34 -0500 Received: by mail-wr1-f71.google.com with SMTP id ffacd0b85a97d-385d735965bso2462079f8f.1 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:37:34 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38631f73237sm8542192f8f.62.2024.12.09.04.37.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:37:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747856; 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=kMi4xnuVX8OtBt4NvX2Y5ZrPSheVzAeHna9cNK+HRcg=; b=YQ/w6OnAq+7zrUdzogBlxXxDO0kTem/u1KQZuD367d/b6xk5JmdpMaABVd01JqBmga3Yu5 LoPMvj0XF8H+XLAhWHTk7qNYH4eMh7w1+zs2O/ju+OC6RNEpOmbY/xFuZtsfNCtKTjUMcQ 3tJG4ofHncK1WkQW2XdBaMHXh5pg+ys= X-MC-Unique: PEGnbFAANT2A19hQSXB9UQ-1 X-Mimecast-MFC-AGG-ID: PEGnbFAANT2A19hQSXB9UQ X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747853; x=1734352653; 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=kMi4xnuVX8OtBt4NvX2Y5ZrPSheVzAeHna9cNK+HRcg=; b=G4ITiYpVQdeFwR81CgEd8wCBkAoUWUAgoFDOcoghK0lmH/W2uZqEKL2VnsWowbbjQ4 AbtwJUaLG4sC1f2WMTP1YbAqCfatglT5OPdVFmjGSoLyg40SP6qmi/xJT7M6it8dmCSS U9j1xun4jKgp/U9cXV/Ew7HnsCL8GQhHmKcXyynA/0JbhdByN7LnoNLuJj8XmVcXYSRn aoj1EVY3oN1RDjB0l/Zu00z1tYYtynogfbPVlHZSn46/boKBuEpmpHqtvxblYUdDOh5k kYBN5vjlgeeENEhOBNHW9NAMtbf+Pn3f1G31YECzYaSgUV55IBNFh7WGSdaOwqm8CRT5 atKQ== X-Gm-Message-State: AOJu0Yz//fqAlRlJJWPahkNXATgVBAdI1s5wOnbagsPoIrODEFoxRvpy BzuxLJvSFgPM6fU/pDy4fQeG9k0hGJjCGaQNZBas7N0P/+jSFlzrce9K0iy1jVMf4M3tGkCuRxK Ike+Vu6vEaPfmgveuw0Lfux7vToUtoltfc6UxWQjzeJefIyTmGRfAH6i5T5fAdsat9jM2gJklSu eYduQL4XiVnxccC69sVCoA0R3rC0BMZk4rYXXL X-Gm-Gg: ASbGncuy6p8yNyStIGH44K3H8UrsySJznEYHwjbxYLOOIr+u/iVi9pQIaGF1AxCA5fi dE7py7IFfY+rciMOWDUWts5OvIFwxng4JkOjOPKe4tma6d7E0WUR0OIQwqdJi0b/B49Z5XmmKBn OIx8BoMx0JstJKoFwwclmnzr4lIjKdYLvBJDLRbFPgZkxrQfTxaGQ0UcNdaXs5w1CRQzzFR/sjl w/fqyAUAhpP6melH0o7CezXmZN3+k5L7oPPT2xnPiZUzLSAtvMTvg== X-Received: by 2002:a05:6000:178e:b0:385:f44a:a3b with SMTP id ffacd0b85a97d-386453fbc58mr130450f8f.41.1733747852538; Mon, 09 Dec 2024 04:37:32 -0800 (PST) X-Google-Smtp-Source: AGHT+IF/iT4fmLKeJ7K00LiiDhtP6Su1hZ8lIxqXurPNj68EnoU02xmTI7gUQl3CvAfSj0cGlXBtjg== X-Received: by 2002:a05:6000:178e:b0:385:f44a:a3b with SMTP id ffacd0b85a97d-386453fbc58mr130422f8f.41.1733747852001; Mon, 09 Dec 2024 04:37:32 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 05/26] rust: add bindings for interrupt sources Date: Mon, 9 Dec 2024 13:36:56 +0100 Message-ID: <20241209123717.99077-6-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=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: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733748080778116600 Content-Type: text/plain; charset="utf-8" The InterruptSource bindings let us call qemu_set_irq() and sysbus_init_irq= () as safe code. Interrupt sources, qemu_irq in C code, are pointers to IRQState objects. They are QOM link properties and can be written to outside the control of the device (i.e. from a shared reference); therefore they must be interior-mutable in Rust. Since thread-safety is provided by the BQL, what we want here is the newly-introduced BqlCell. A pointer to the contents of the BqlCell (an IRQState**, or equivalently qemu_irq*) is then passed to the C sysbus_init_irq function. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Zhao Liu <zhao1.liu@intel.com> --- rust/hw/char/pl011/src/device.rs | 22 ++++---- rust/qemu-api/meson.build | 2 + rust/qemu-api/src/irq.rs | 91 ++++++++++++++++++++++++++++++++ rust/qemu-api/src/lib.rs | 2 + rust/qemu-api/src/sysbus.rs | 27 ++++++++++ 5 files changed, 134 insertions(+), 10 deletions(-) create mode 100644 rust/qemu-api/src/irq.rs create mode 100644 rust/qemu-api/src/sysbus.rs diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index 317a9b3c5ad..c5c8c463d37 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -13,6 +13,7 @@ c_str, definitions::ObjectImpl, device_class::TYPE_SYS_BUS_DEVICE, + irq::InterruptSource, }; =20 use crate::{ @@ -94,7 +95,7 @@ pub struct PL011State { /// * sysbus IRQ 5: `UARTEINTR` (error interrupt line) /// ``` #[doc(alias =3D "irq")] - pub interrupts: [qemu_irq; 6usize], + pub interrupts: [InterruptSource; IRQMASK.len()], #[doc(alias =3D "clk")] pub clock: NonNull<Clock>, #[doc(alias =3D "migrate_clk")] @@ -139,7 +140,8 @@ impl PL011State { unsafe fn init(&mut self) { const CLK_NAME: &CStr =3D c_str!("clk"); =20 - let dev =3D addr_of_mut!(*self).cast::<DeviceState>(); + let sbd =3D unsafe { &mut *(addr_of_mut!(*self).cast::<SysBusDevic= e>()) }; + // SAFETY: // // self and self.iomem are guaranteed to be valid at this point si= nce callers @@ -153,12 +155,15 @@ unsafe fn init(&mut self) { Self::TYPE_INFO.name, 0x1000, ); - let sbd =3D addr_of_mut!(*self).cast::<SysBusDevice>(); sysbus_init_mmio(sbd, addr_of_mut!(self.iomem)); - for irq in self.interrupts.iter_mut() { - sysbus_init_irq(sbd, irq); - } } + + for irq in self.interrupts.iter() { + sbd.init_irq(irq); + } + + let dev =3D addr_of_mut!(*self).cast::<DeviceState>(); + // SAFETY: // // self.clock is not initialized at this point; but since `NonNull= <_>` is Copy, @@ -498,10 +503,7 @@ pub fn put_fifo(&mut self, value: c_uint) { pub fn update(&self) { let flags =3D self.int_level & self.int_enabled; for (irq, i) in self.interrupts.iter().zip(IRQMASK) { - // SAFETY: self.interrupts have been initialized in init(). - unsafe { - qemu_set_irq(*irq, i32::from(flags & i !=3D 0)); - } + irq.set(flags & i !=3D 0); } } =20 diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build index f8b4cd39a26..b927eb58c8e 100644 --- a/rust/qemu-api/meson.build +++ b/rust/qemu-api/meson.build @@ -20,8 +20,10 @@ _qemu_api_rs =3D static_library( 'src/c_str.rs', 'src/definitions.rs', 'src/device_class.rs', + 'src/irq.rs', 'src/offset_of.rs', 'src/prelude.rs', + 'src/sysbus.rs', 'src/vmstate.rs', 'src/zeroable.rs', ], diff --git a/rust/qemu-api/src/irq.rs b/rust/qemu-api/src/irq.rs new file mode 100644 index 00000000000..6258141bdf0 --- /dev/null +++ b/rust/qemu-api/src/irq.rs @@ -0,0 +1,91 @@ +// Copyright 2024 Red Hat, Inc. +// Author(s): Paolo Bonzini <pbonzini@redhat.com> +// SPDX-License-Identifier: GPL-2.0-or-later + +//! Bindings for interrupt sources + +use core::ptr; +use std::{marker::PhantomData, os::raw::c_int}; + +use crate::{ + bindings::{qemu_set_irq, IRQState}, + prelude::*, +}; + +/// Interrupt sources are used by devices to pass changes to a value (typi= cally +/// a boolean). The interrupt sink is usually an interrupt controller or +/// GPIO controller. +/// +/// As far as devices are concerned, interrupt sources are always active-h= igh: +/// for example, `InterruptSource<bool>`'s [`raise`](InterruptSource::rais= e) +/// method sends a `true` value to the sink. If the guest has to see a +/// different polarity, that change is performed by the board between the +/// device and the interrupt controller. +/// +/// Interrupts are implemented as a pointer to the interrupt "sink", which= has +/// type [`IRQState`]. A device exposes its source as a QOM link property= using +/// a function such as +/// [`SysBusDevice::init_irq`](crate::sysbus::SysBusDevice::init_irq), and +/// initially leaves the pointer to a NULL value, representing an unconnec= ted +/// interrupt. To connect it, whoever creates the device fills the pointer= with +/// the sink's `IRQState *`, for example using `sysbus_connect_irq`. Beca= use +/// devices are generally shared objects, interrupt sources are an example= of +/// the interior mutability pattern. +/// +/// Interrupt sources can only be triggered under the Big QEMU Lock; `BqlC= ell` +/// allows access from whatever thread has it. +#[derive(Debug)] +#[repr(transparent)] +pub struct InterruptSource<T =3D bool> +where + c_int: From<T>, +{ + cell: BqlCell<*mut IRQState>, + _marker: PhantomData<T>, +} + +impl InterruptSource<bool> { + /// Send a low (`false`) value to the interrupt sink. + pub fn lower(&self) { + self.set(false); + } + + /// Send a high-low pulse to the interrupt sink. + pub fn pulse(&self) { + self.set(true); + self.set(false); + } + + /// Send a high (`true`) value to the interrupt sink. + pub fn raise(&self) { + self.set(true); + } +} + +impl<T> InterruptSource<T> +where + c_int: From<T>, +{ + /// Send `level` to the interrupt sink. + pub fn set(&self, level: T) { + let ptr =3D self.cell.get(); + // SAFETY: the pointer is retrieved under the BQL and remains valid + // until the BQL is released, which is after qemu_set_irq() is ent= ered. + unsafe { + qemu_set_irq(ptr, level.into()); + } + } + + pub(crate) const fn as_ptr(&self) -> *mut *mut IRQState { + self.cell.as_ptr() + } +} + +impl Default for InterruptSource { + fn default() -> Self { + InterruptSource { + cell: BqlCell::new(ptr::null_mut()), + _marker: PhantomData, + } + } +} diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs index e5956cd5eb6..0efbef47441 100644 --- a/rust/qemu-api/src/lib.rs +++ b/rust/qemu-api/src/lib.rs @@ -16,7 +16,9 @@ pub mod cell; pub mod definitions; pub mod device_class; +pub mod irq; pub mod offset_of; +pub mod sysbus; pub mod vmstate; pub mod zeroable; =20 diff --git a/rust/qemu-api/src/sysbus.rs b/rust/qemu-api/src/sysbus.rs new file mode 100644 index 00000000000..4e192c75898 --- /dev/null +++ b/rust/qemu-api/src/sysbus.rs @@ -0,0 +1,27 @@ +// Copyright 2024 Red Hat, Inc. +// Author(s): Paolo Bonzini <pbonzini@redhat.com> +// SPDX-License-Identifier: GPL-2.0-or-later + +use std::ptr::addr_of; + +pub use bindings::{SysBusDevice, SysBusDeviceClass}; + +use crate::{bindings, cell::bql_locked, irq::InterruptSource}; + +impl SysBusDevice { + /// Return `self` cast to a mutable pointer, for use in calls to C cod= e. + const fn as_mut_ptr(&self) -> *mut SysBusDevice { + addr_of!(*self) as *mut _ + } + + /// Expose an interrupt source outside the device as a qdev GPIO outpu= t. + /// Note that the ordering of calls to `init_irq` is important, since + /// whoever creates the sysbus device will refer to the interrupts with + /// a number that corresponds to the order of calls to `init_irq`. + pub fn init_irq(&self, irq: &InterruptSource) { + assert!(bql_locked()); + unsafe { + bindings::sysbus_init_irq(self.as_mut_ptr(), irq.as_ptr()); + } + } +} --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733747973; cv=none; d=zohomail.com; s=zohoarc; b=XkZ/KFNFxpBP5Lfc7haBE3mgc+gADPNQFCNIgM5V0n0qCrw5JRVG4GqDXPjKbKwrrlaW6rc841t6bKxplSHy9hKe+wycK9gqQKHywtZvWdTz0hN9Yo6aYQ15F+oh/gBvk34jg9dKxHaiGqnfvHckSRFxjYU/KnEvDO9SZ5e08iM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733747973; 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=sBwsf4s6VXMmXVQEquo962VkkBl6Oft5lKCFdPBoVSc=; b=iWrGfSGOMRBhl3z6zGhK0nHnHkJI47zcTe4wLnX+CQPaYO9RvIViGl8/A6339oe7BFpGmy8UDysLnL4FrB+0GgZQfkncynukbRXnXv3EcwVUnorPUH8TClhmVAvTpvFmOgVCtp5qSHr41cdMg71nW2ulPDYzM7XuRq1O8zGq060= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733747973282210.92633901216675; Mon, 9 Dec 2024 04:39:33 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd1S-0003y4-AG; Mon, 09 Dec 2024 07:37:58 -0500 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 <pbonzini@redhat.com>) id 1tKd1M-0003rz-KM for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:52 -0500 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 <pbonzini@redhat.com>) id 1tKd1D-0007Pp-Ck for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:48 -0500 Received: from mail-wr1-f72.google.com (mail-wr1-f72.google.com [209.85.221.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-629-TO0LMUN5PJWaVwfaPIm0Ow-1; Mon, 09 Dec 2024 07:37:37 -0500 Received: by mail-wr1-f72.google.com with SMTP id ffacd0b85a97d-386321c8f4bso1237657f8f.0 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:37:37 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-386221a62f2sm12984210f8f.105.2024.12.09.04.37.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:37:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747858; 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=sBwsf4s6VXMmXVQEquo962VkkBl6Oft5lKCFdPBoVSc=; b=Y+dA60GGJoaqKlm87aH4hmlEZTbty/4GCQU+pz4sguZxYlpOrmkl4HdUP2DgFmH8NfwgZG nA2Ve7QAOhJO/rQxShqDsjzueFDPJVBMaj8r+3NdKZCpoislJDz1hH5vWH5THvEyXYwXW1 qiV1lrPHXCO+0yDXwvHDlfcu4hR7Un8= X-MC-Unique: TO0LMUN5PJWaVwfaPIm0Ow-1 X-Mimecast-MFC-AGG-ID: TO0LMUN5PJWaVwfaPIm0Ow X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747855; x=1734352655; 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=sBwsf4s6VXMmXVQEquo962VkkBl6Oft5lKCFdPBoVSc=; b=r2IBs/jcPMBHR33gca/WJtrEbu8PyZSA0zMZX+ydZAqyb2lsoJj6lowwDeI/BBmhZq BTDkdAOqfXUGlZwsXrhMrO3e8VdtnzgPzcyJolIUJNAUJ3r1SkataKXMdWZYmNpv2A4B xVqWDKnJrX6Y/a6QAkDJVU2584DFJc6IPYST9E0rktUcdbjyyUk+btYARIOKEPiaP7SF qJYo8eVqE+19+E70aBnxV+/r2Yo68VzG3l83aNn7Eex6SHJJfn1FrhTqaEzrrNDpInXm EhfBHoPseCVGqkgguPcTPJdlVehxx2+o9cUqknohWzo/tPptvan47vnpiRqBn7QtqC86 BueA== X-Gm-Message-State: AOJu0YxeiUxfIeZnJZXuONmL15EcjcEtLEbP9VbUiHe8iSSL5ys+nNr2 jciy3SahrMey6qSldJ5bBapQvY9qojPdgw3WdOHw0iHSKFoduuikXPmv8mQobQ+AusQLcHmBMrP fYMC3G+9QSLP8NSqOXZZte5oFXXdh54qXn0ZO0n5kX9fkGSqja8s7Q7dllJmHTA6Nr+aLQiqezt VrFrJlJEqt0Sea5s6jjJzXGypBg6JqihCtdtrJ X-Gm-Gg: ASbGnctJHVLpC/lJisz6NwCxlS4idGDqrNuIaJ4Y95WNOf/s82fy6wGT9UsE4VPW+BU Q/gIAUVQrs3K8zaWBug3RUXevRY67qNulX5NGmq8qARrEVqnxzH4sz7yaQHs87KRg/wFipRNFtr Bi6EJ3R40zEp+K5hveyg6ZBqnZUyGPRlrMD9ONrnuB7MVjphiDrypeh2149VxjBI633V4q14vLn zWWn70jL1XBTaZGbdCCnKZV7m9rwy3jkuSNbe8x9eWuBgfFw4196Q== X-Received: by 2002:a05:6000:178e:b0:386:8ff:d20b with SMTP id ffacd0b85a97d-386453def96mr159959f8f.27.1733747854844; Mon, 09 Dec 2024 04:37:34 -0800 (PST) X-Google-Smtp-Source: AGHT+IHjporSdgQ1wAOgDZrCeoKxDdS9DTZ2gGKSzKXGXlzKxxnAGAbEQwy9CfjSOYBE62A3bTbiDg== X-Received: by 2002:a05:6000:178e:b0:386:8ff:d20b with SMTP id ffacd0b85a97d-386453def96mr159929f8f.27.1733747854348; Mon, 09 Dec 2024 04:37:34 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 06/26] rust: add a bit operation module Date: Mon, 9 Dec 2024 13:36:57 +0100 Message-ID: <20241209123717.99077-7-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733747974370116600 Content-Type: text/plain; charset="utf-8" The bindgen supports `static inline` function binding since v0.64.0 as an experimental feature (`--wrap-static-fns`), and stabilizes it after v0.70.0. But the oldest version of bindgen supported by QEMU is v0.60.1, so there's no way to generate the binding for deposit64() which is `static inline` (in include/qemu/bitops.h). Instead, implement it by hand in Rust and make it available for all unsigned types through an IntegerExt trait. Since it only involves bit operations, the Rust version of the code is almost identical to the original C version, but it applies to more types than just u64. Signed-off-by: Zhao Liu <zhao1.liu@intel.com> Co-authored-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Zhao Liu <zhao1.liu@intel.com> --- rust/qemu-api/meson.build | 1 + rust/qemu-api/src/bitops.rs | 119 +++++++++++++++++++++++++++++++++++ rust/qemu-api/src/lib.rs | 1 + rust/qemu-api/src/prelude.rs | 2 + 4 files changed, 123 insertions(+) create mode 100644 rust/qemu-api/src/bitops.rs diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build index b927eb58c8e..adcee661150 100644 --- a/rust/qemu-api/meson.build +++ b/rust/qemu-api/meson.build @@ -16,6 +16,7 @@ _qemu_api_rs =3D static_library( [ 'src/lib.rs', 'src/bindings.rs', + 'src/bitops.rs', 'src/cell.rs', 'src/c_str.rs', 'src/definitions.rs', diff --git a/rust/qemu-api/src/bitops.rs b/rust/qemu-api/src/bitops.rs new file mode 100644 index 00000000000..5acd6642d1a --- /dev/null +++ b/rust/qemu-api/src/bitops.rs @@ -0,0 +1,119 @@ +// Copyright (C) 2024 Intel Corporation. +// Author(s): Zhao Liu <zhai1.liu@intel.com> +// SPDX-License-Identifier: GPL-2.0-or-later + +//! This module provides bit operation extensions to integer types. +//! It is usually included via the `qemu_api` prelude. + +use std::ops::{ + Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitX= orAssign, Div, DivAssign, + Mul, MulAssign, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, +}; + +/// Trait for extensions to integer types +pub trait IntegerExt: + Add<Self, Output =3D Self> + AddAssign<Self> + + BitAnd<Self, Output =3D Self> + BitAndAssign<Self> + + BitOr<Self, Output =3D Self> + BitOrAssign<Self> + + BitXor<Self, Output =3D Self> + BitXorAssign<Self> + + Copy + + Div<Self, Output =3D Self> + DivAssign<Self> + + Eq + + Mul<Self, Output =3D Self> + MulAssign<Self> + + Not<Output =3D Self> + Ord + PartialOrd + + Rem<Self, Output =3D Self> + RemAssign<Self> + + Shl<Self, Output =3D Self> + ShlAssign<Self> + + Shl<u32, Output =3D Self> + ShlAssign<u32> + // add more as needed + Shr<Self, Output =3D Self> + ShrAssign<Self> + + Shr<u32, Output =3D Self> + ShrAssign<u32> // add more as needed +{ + const BITS: u32; + const MAX: Self; + const MIN: Self; + const ONE: Self; + const ZERO: Self; + + #[inline] + #[must_use] + fn bit(start: u32) -> Self + { + assert!(start <=3D Self::BITS); + + Self::ONE << start + } + + #[inline] + #[must_use] + fn mask(start: u32, length: u32) -> Self + { + /* FIXME: Implement a more elegant check with error handling suppo= rt? */ + assert!(length > 0 && length <=3D Self::BITS - start); + + (Self::MAX >> (Self::BITS - length)) << start + } + + #[inline] + #[must_use] + fn deposit<U: IntegerExt>(self, start: u32, length: u32, + fieldval: U) -> Self + where Self: From<U> + { + debug_assert!(length <=3D U::BITS); + + let mask =3D Self::mask(start, length); + (self & !mask) | ((Self::from(fieldval) << start) & mask) + } + + #[inline] + #[must_use] + fn extract(self, start: u32, length: u32) -> Self + { + let mask =3D Self::mask(start, length); + (self & mask) >> start + } +} + +macro_rules! impl_num_ext { + ($type:ty) =3D> { + impl IntegerExt for $type { + const BITS: u32 =3D <$type>::BITS; + const MAX: Self =3D <$type>::MAX; + const MIN: Self =3D <$type>::MIN; + const ONE: Self =3D 1; + const ZERO: Self =3D 0; + } + }; +} + +impl_num_ext!(u8); +impl_num_ext!(u16); +impl_num_ext!(u32); +impl_num_ext!(u64); + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_deposit() { + assert_eq!(15u32.deposit(8, 8, 1u32), 256 + 15); + assert_eq!(15u32.deposit(8, 1, 255u8), 256 + 15); + } + + #[test] + fn test_extract() { + assert_eq!(15u32.extract(2, 4), 3); + } + + #[test] + fn test_bit() { + assert_eq!(u8::bit(7), 128); + assert_eq!(u32::bit(16), 0x10000); + } + + #[test] + fn test_mask() { + assert_eq!(u8::mask(7, 1), 128); + assert_eq!(u32::mask(8, 8), 0xff00); + } +} diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs index 0efbef47441..9e007e16354 100644 --- a/rust/qemu-api/src/lib.rs +++ b/rust/qemu-api/src/lib.rs @@ -12,6 +12,7 @@ #[rustfmt::skip] pub mod prelude; =20 +pub mod bitops; pub mod c_str; pub mod cell; pub mod definitions; diff --git a/rust/qemu-api/src/prelude.rs b/rust/qemu-api/src/prelude.rs index dfaddbd062a..a39e228babf 100644 --- a/rust/qemu-api/src/prelude.rs +++ b/rust/qemu-api/src/prelude.rs @@ -2,5 +2,7 @@ // Author(s): Paolo Bonzini <pbonzini@redhat.com> // SPDX-License-Identifier: GPL-2.0-or-later =20 +pub use crate::bitops::IntegerExt; + pub use crate::cell::BqlCell; pub use crate::cell::BqlRefCell; --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733748714; cv=none; d=zohomail.com; s=zohoarc; b=dhz/AeLjJILc63Qvdzm8+V/1ZcKd1n9gLdTu1jGoQUcEV+Rz5BDwZULzaFZJd58AoUwSuFx/HGHFuE1lDHZD6r490IjDvu2EvNi40NQP66FRGOc4csL44ECHBeFwXWfc6ph7LppJ9esIl8YGWN+ErJk9lhFjNXgI5Oaa6JZo570= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733748714; 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=d/CuNDAf/h1lPd4tHb600O5eISjRNvbweuEs0GGCzf8=; b=FXYdeUjPDjFXYK6IrD8UPb5wp79I+i691NEWRwDZJkg77xQSA5TmEK3MEKKHnPxmJ/hD9LowtZozgOJUUdIwOUKbZ+6DxA9lzgDyUkl90cplOOIgn2GLZzGVqssyu3gPzKOe9NfmhPMCGSo+8XxsxoXO14Immko1zIYz+W+xgh4= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733748714247448.6489880848909; Mon, 9 Dec 2024 04:51:54 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd1O-0003ul-4R; Mon, 09 Dec 2024 07:37:54 -0500 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 <pbonzini@redhat.com>) id 1tKd1M-0003s0-Kj for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:52 -0500 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 <pbonzini@redhat.com>) id 1tKd1E-0007Q8-PQ for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:50 -0500 Received: from mail-wm1-f70.google.com (mail-wm1-f70.google.com [209.85.128.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-447-LppsLzdCPvewx-pvpsPnqQ-1; Mon, 09 Dec 2024 07:37:39 -0500 Received: by mail-wm1-f70.google.com with SMTP id 5b1f17b1804b1-434e8beee61so9513785e9.0 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:37:39 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-434d52c0be4sm191423765e9.28.2024.12.09.04.37.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:37:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747860; 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=d/CuNDAf/h1lPd4tHb600O5eISjRNvbweuEs0GGCzf8=; b=JXpmucRdOBFy6WweyI04LSvQW/FoWA283cYKpzp90t7sKRtrFoiww2fXZaGZNDrxDefpp7 f/6l82jlX68mbJpK+Id9zFnhwPkRJc3ydKOofdeYiepFs7QIaSLJ6cUJgOjbIvBAnXWDK6 c5moH9PJPnykApOzOqlz9vYZmKrh/Ls= X-MC-Unique: LppsLzdCPvewx-pvpsPnqQ-1 X-Mimecast-MFC-AGG-ID: LppsLzdCPvewx-pvpsPnqQ X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747858; x=1734352658; 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=d/CuNDAf/h1lPd4tHb600O5eISjRNvbweuEs0GGCzf8=; b=NVlMQlW6L1xPuMf9eYjEgTmTp8HKMhIKOFcyLBU8+NhO7alWQuxgPK9pKib5EQj+gd F+DI5VbTlUNcV8cf8c7ALF6ooE6G4HQMP82HpsYX9JmS1zz8Rc//D7KZ9ksWBdleXhcw CqyeyZ3jJrU688XUB70JD/ew34PnL4c1zwM9RTpONVIOzUJ7ZwpbqP68K6Onb+fH3+IQ whXDtMrdTUH8NNh2mMx1E0ToWzOSUctcClzDIpPcQGDTP7+D3Qi0Abrb0wKGiCz8/ZJp Qf58pYuakW8dL7RoBMeRZhkR5/TBvw+Z7AK444maF+1aPLPSLrZmLME9e7ihTxeENY2k +H4A== X-Gm-Message-State: AOJu0YygkeMPeAXt9Mvf9TC9rEUfrubTENMyp7dtezBbvAVpkeYDdNEq K2cBBMuBNp6L2ZrDvUZ2jAk4f73f7BiOJIqisjucjqxTwi036dE9OeqSrtsF2BrwqKHmx0tytpT npkbs4hjIvFXI7+uF8LVIRsv7E/YeyL3W/larWHA2ZXqjGPWalSen5F6OrxHIFeZLBCbFJ7klFS x71qEY3u8PWTJifeMsQ1DhODXI/lIWag43JKF9 X-Gm-Gg: ASbGncurqKHg7d5VD8zrOANZxDI1hD1dfdfWDQSe9lSQEE5FgBmnvxPXRx2ljHUINsi BapLz7ETZVzh1YHIh1fHc8xC5YYIIVBdEqwGoBGk4ZH/9ADBQff5NrHwdxb9K/0LGT2XkvyhT6J CTpg9I7CXqikZMJhuIaBj8nniAvsj/vDbeFSymlh+ask5rFJlnkspYdyCniA2A3XrQFhHih4/Uc D3q0mIW0nW8C36vvDMqq1+zxR7YWl93iRIXLxEGJo9nWmnSddlPoQ== X-Received: by 2002:a05:600c:3b1e:b0:434:9d3c:31ec with SMTP id 5b1f17b1804b1-434d92bf66amr121068015e9.10.1733747857763; Mon, 09 Dec 2024 04:37:37 -0800 (PST) X-Google-Smtp-Source: AGHT+IEKosmxVjsdlGtzG1n53ELAg0Tz6RFW8udLUmBqIrFlJPlfcQ6F4Dy5UXlW6uhM4cO07tODkg== X-Received: by 2002:a05:600c:3b1e:b0:434:9d3c:31ec with SMTP id 5b1f17b1804b1-434d92bf66amr121067765e9.10.1733747857319; Mon, 09 Dec 2024 04:37:37 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 07/26] rust: qom: add default definitions for ObjectImpl Date: Mon, 9 Dec 2024 13:36:58 +0100 Message-ID: <20241209123717.99077-8-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=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: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733748823969116600 Content-Type: text/plain; charset="utf-8" Remove a bunch of duplicate const definitions. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Zhao Liu <zhao1.liu@intel.com> --- rust/hw/char/pl011/src/device.rs | 6 ------ rust/qemu-api/src/definitions.rs | 8 ++++---- rust/qemu-api/tests/tests.rs | 4 ---- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index c5c8c463d37..3d173ae816d 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -109,10 +109,7 @@ impl ObjectImpl for PL011State { const TYPE_INFO: qemu_api::bindings::TypeInfo =3D qemu_api::type_info!= { Self }; const TYPE_NAME: &'static CStr =3D crate::TYPE_PL011; const PARENT_TYPE_NAME: Option<&'static CStr> =3D Some(TYPE_SYS_BUS_DE= VICE); - const ABSTRACT: bool =3D false; const INSTANCE_INIT: Option<unsafe extern "C" fn(obj: *mut Object)> = =3D Some(pl011_init); - const INSTANCE_POST_INIT: Option<unsafe extern "C" fn(obj: *mut Object= )> =3D None; - const INSTANCE_FINALIZE: Option<unsafe extern "C" fn(obj: *mut Object)= > =3D None; } =20 #[repr(C)] @@ -666,8 +663,5 @@ impl ObjectImpl for PL011Luminary { const TYPE_INFO: qemu_api::bindings::TypeInfo =3D qemu_api::type_info!= { Self }; const TYPE_NAME: &'static CStr =3D crate::TYPE_PL011_LUMINARY; const PARENT_TYPE_NAME: Option<&'static CStr> =3D Some(crate::TYPE_PL0= 11); - const ABSTRACT: bool =3D false; const INSTANCE_INIT: Option<unsafe extern "C" fn(obj: *mut Object)> = =3D Some(pl011_luminary_init); - const INSTANCE_POST_INIT: Option<unsafe extern "C" fn(obj: *mut Object= )> =3D None; - const INSTANCE_FINALIZE: Option<unsafe extern "C" fn(obj: *mut Object)= > =3D None; } diff --git a/rust/qemu-api/src/definitions.rs b/rust/qemu-api/src/definitio= ns.rs index 26597934bbd..92b3c6f9118 100644 --- a/rust/qemu-api/src/definitions.rs +++ b/rust/qemu-api/src/definitions.rs @@ -14,10 +14,10 @@ pub trait ObjectImpl { const TYPE_INFO: TypeInfo; const TYPE_NAME: &'static CStr; const PARENT_TYPE_NAME: Option<&'static CStr>; - const ABSTRACT: bool; - const INSTANCE_INIT: Option<unsafe extern "C" fn(obj: *mut Object)>; - const INSTANCE_POST_INIT: Option<unsafe extern "C" fn(obj: *mut Object= )>; - const INSTANCE_FINALIZE: Option<unsafe extern "C" fn(obj: *mut Object)= >; + const ABSTRACT: bool =3D false; + const INSTANCE_INIT: Option<unsafe extern "C" fn(obj: *mut Object)> = =3D None; + const INSTANCE_POST_INIT: Option<unsafe extern "C" fn(obj: *mut Object= )> =3D None; + const INSTANCE_FINALIZE: Option<unsafe extern "C" fn(obj: *mut Object)= > =3D None; } =20 pub trait Class { diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index 925f5a3c77b..f793ff26e5d 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -58,10 +58,6 @@ impl ObjectImpl for DummyState { const TYPE_INFO: qemu_api::bindings::TypeInfo =3D qemu_api::type_i= nfo! { Self }; const TYPE_NAME: &'static CStr =3D c_str!("dummy"); const PARENT_TYPE_NAME: Option<&'static CStr> =3D Some(device_clas= s::TYPE_DEVICE); - const ABSTRACT: bool =3D false; - const INSTANCE_INIT: Option<unsafe extern "C" fn(obj: *mut Object)= > =3D None; - const INSTANCE_POST_INIT: Option<unsafe extern "C" fn(obj: *mut Ob= ject)> =3D None; - const INSTANCE_FINALIZE: Option<unsafe extern "C" fn(obj: *mut Obj= ect)> =3D None; } =20 impl Class for DummyClass { --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733748478; cv=none; d=zohomail.com; s=zohoarc; b=nGMyyiSUgOCqUjIht9DK5awjTGE0vQAFgk+bsJVu7vf9/1WEJTOcfjNFJLJ7h3ckARxfYujAz3LA6erBt0UVbaPATh7vvHJ/MNe5FNXD1J8gSeEnoupi4ktkcSjiig7+doPdI8+deBfQ3GeBXvPZ/RIYtNtEPHgZJHTVbCysTok= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733748478; 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=V2ZIv/PAvz3komJwq6oypf8CScK5YKxPKfhuCNRvYs8=; b=Sxv6eDpLCm1W7q1Lt0x9w6LF9tp2i9utmX6Ca2w2GVELGh7NygxzVmDbG+KyHBEWyxTykFl2JPY2UCQP79oyb7DLNtglWN3PC9qJJukCXHm4BeqHCSJqhcVWj+ENx8DoJKoPijvBGPOhoT2TXn0ZEnWYGb0iPrL1IWd2uV/DTUU= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733748478671123.9253432916721; Mon, 9 Dec 2024 04:47:58 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd1T-0003yh-Au; Mon, 09 Dec 2024 07:37:59 -0500 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 <pbonzini@redhat.com>) id 1tKd1O-0003wP-Sh for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:55 -0500 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 <pbonzini@redhat.com>) id 1tKd1F-0007QW-Pt for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:54 -0500 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-580-Q78XRElBOKGkjTW2D88B-Q-1; Mon, 09 Dec 2024 07:37:42 -0500 Received: by mail-wm1-f69.google.com with SMTP id 5b1f17b1804b1-434fff37885so669195e9.3 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:37:41 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-434da0d69dfsm153106035e9.14.2024.12.09.04.37.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:37:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747864; 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=V2ZIv/PAvz3komJwq6oypf8CScK5YKxPKfhuCNRvYs8=; b=A/lsY9wBaT4SRVdI5JgEFcBMayNnbcwJS3ZgMEqCUpRNgZDcZEFRvNmCAHHZJQxCkHC4bL PCPtrz3+YTgkz65KbLdGpxgvflOUNkKNM782eO3VdwsFqMDas6dpJZC2p3AhLfBoPzcwnx WNj3DsHgPlNqYIbGPYt2sPxfdQinYJo= X-MC-Unique: Q78XRElBOKGkjTW2D88B-Q-1 X-Mimecast-MFC-AGG-ID: Q78XRElBOKGkjTW2D88B-Q X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747860; x=1734352660; 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=V2ZIv/PAvz3komJwq6oypf8CScK5YKxPKfhuCNRvYs8=; b=ANOhALfNe11R6ustUKKSubEfplZSXR3RsrcMO9YBtEdiBbCWrngrQ/ra2/cVje07Dm 9TX+mbmKMMo5JBrOzSeEm8npqRTqTOTgd6Ghkv76r7xpsk/oVgwF4704M4pm/Jl8V7w7 FOrNkQ9AWBsVoC7r0IjuieO4McrXg5zgmyKfZp1c+5E8JZQkJY7tfNIVNhXxc7E66oe2 WAL33SzIjeqc/tIxEz5k0JOv6iVnfuPqRqfvsJ1kSXIQhiutUfLBI7ci9u+1CZEUMY8y TNXKa2fkv0Ef42EnjQiRPFxzlFzOj9zXqommQnIVcOv4L8I8j1tw+gUcI4jfDrWRhVAK bnZw== X-Gm-Message-State: AOJu0YzWf/UuXwSLyXWLRwGrieyn4jUU2b1rPQZol+vuN3g1urODoBIw ggCQvt9/9h9fkKWQCf7udWoimFU8YxopRNRV1U99m+TZZQcWtjM93ylhe3zrfb64Vt7BMBBDCe4 8OgTs2d1RHtVvLiG45wGVD8rYfNnLLqY9bsXyhLHzYpGp/aVMxJGJHxm4+iZ9dYZv7Ax3ao69sr cMIIvh/9ESfPCOvyI1Z+w+x3Tzr7m4uqZwAnxy X-Gm-Gg: ASbGncuqobaS1cy4koZsmsVqJCsnb/bQw8Q9+UzaTapIEaDQkfkqm/kAvICnijG4gsl QTf4hgqsqI1/orBVXH9XBXwn/Ctm7MZnNd8bRtuKD2RLyAl7gNpjyFTLsq3PIeC4jNSa8kOZIf5 fFsUDP/0+sMAvq+0rhjw/iX96yljf3uNwM60WbAFGfY2v0XEspZoR+Jiz204jYY/z9x9tZtr5mg OEqSlzJ+DKVRzM2VfbWN8BWcEjsnDnZBqf1CBGy8CEtAUw73CTwdQ== X-Received: by 2002:a05:600c:5108:b0:434:a7b6:10e0 with SMTP id 5b1f17b1804b1-434fff80a6cmr2781205e9.18.1733747859810; Mon, 09 Dec 2024 04:37:39 -0800 (PST) X-Google-Smtp-Source: AGHT+IGTzrWqUo1UrlDef9gTX0dvO1xC+x7VjkryApIESqwOJvaVHc0eFXP98N3waTQkkhIbvtJ4BQ== X-Received: by 2002:a05:600c:5108:b0:434:a7b6:10e0 with SMTP id 5b1f17b1804b1-434fff80a6cmr2780875e9.18.1733747859365; Mon, 09 Dec 2024 04:37:39 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 08/26] rust: qom: rename Class trait to ClassInitImpl Date: Mon, 9 Dec 2024 13:36:59 +0100 Message-ID: <20241209123717.99077-9-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=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: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733748480610116600 Content-Type: text/plain; charset="utf-8" While at it, document it. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Zhao Liu <zhao1.liu@intel.com> --- rust/hw/char/pl011/src/device.rs | 4 ++-- rust/qemu-api/src/definitions.rs | 25 ++++++++++++++++++++++--- rust/qemu-api/tests/tests.rs | 4 ++-- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index 3d173ae816d..bd12067aaf0 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -117,7 +117,7 @@ pub struct PL011Class { _inner: [u8; 0], } =20 -impl qemu_api::definitions::Class for PL011Class { +impl qemu_api::definitions::ClassInitImpl for PL011Class { const CLASS_INIT: Option<unsafe extern "C" fn(klass: *mut ObjectClass,= data: *mut c_void)> =3D Some(crate::device_class::pl011_class_init); const CLASS_BASE_INIT: Option< @@ -650,7 +650,7 @@ pub struct PL011LuminaryClass { } } =20 -impl qemu_api::definitions::Class for PL011LuminaryClass { +impl qemu_api::definitions::ClassInitImpl for PL011LuminaryClass { const CLASS_INIT: Option<unsafe extern "C" fn(klass: *mut ObjectClass,= data: *mut c_void)> =3D None; const CLASS_BASE_INIT: Option< diff --git a/rust/qemu-api/src/definitions.rs b/rust/qemu-api/src/definitio= ns.rs index 92b3c6f9118..3291f4242ce 100644 --- a/rust/qemu-api/src/definitions.rs +++ b/rust/qemu-api/src/definitions.rs @@ -20,8 +20,27 @@ pub trait ObjectImpl { const INSTANCE_FINALIZE: Option<unsafe extern "C" fn(obj: *mut Object)= > =3D None; } =20 -pub trait Class { +/// Trait used to fill in a class struct. +/// +/// Each QOM class that has virtual methods describes them in a +/// _class struct_. Class structs include a parent field corresponding +/// to the vtable of the parent class, all the way up to [`ObjectClass`]. +/// Each QOM type has one such class struct. +/// +/// The Rust implementation of methods will usually come from a trait +/// like [`ObjectImpl`]. +pub trait ClassInitImpl { + /// Function that is called after all parent class initialization + /// has occurred. On entry, the virtual method pointers are set to + /// the default values coming from the parent classes; the function + /// can change them to override virtual methods of a parent class. const CLASS_INIT: Option<unsafe extern "C" fn(klass: *mut ObjectClass,= data: *mut c_void)>; + + /// Called on descendent classes after all parent class initialization + /// has occurred, but before the class itself is initialized. This + /// is only useful if a class is not a leaf, and can be used to undo + /// the effects of copying the contents of the parent's class struct + /// to the descendants. const CLASS_BASE_INIT: Option< unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void), >; @@ -82,8 +101,8 @@ macro_rules! type_info { instance_finalize: <$t as $crate::definitions::ObjectImpl>::IN= STANCE_FINALIZE, abstract_: <$t as $crate::definitions::ObjectImpl>::ABSTRACT, class_size: ::core::mem::size_of::<<$t as $crate::definitions= ::ObjectImpl>::Class>(), - class_init: <<$t as $crate::definitions::ObjectImpl>::Class as= $crate::definitions::Class>::CLASS_INIT, - class_base_init: <<$t as $crate::definitions::ObjectImpl>::Cla= ss as $crate::definitions::Class>::CLASS_BASE_INIT, + class_init: <<$t as $crate::definitions::ObjectImpl>::Class as= $crate::definitions::ClassInitImpl>::CLASS_INIT, + class_base_init: <<$t as $crate::definitions::ObjectImpl>::Cla= ss as $crate::definitions::ClassInitImpl>::CLASS_BASE_INIT, class_data: ::core::ptr::null_mut(), interfaces: ::core::ptr::null_mut(), }; diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index f793ff26e5d..704c63c846f 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -7,7 +7,7 @@ use qemu_api::{ bindings::*, c_str, declare_properties, define_property, - definitions::{Class, ObjectImpl}, + definitions::{ClassInitImpl, ObjectImpl}, device_class, device_class_init, zeroable::Zeroable, }; @@ -60,7 +60,7 @@ impl ObjectImpl for DummyState { const PARENT_TYPE_NAME: Option<&'static CStr> =3D Some(device_clas= s::TYPE_DEVICE); } =20 - impl Class for DummyClass { + impl ClassInitImpl for DummyClass { const CLASS_INIT: Option<unsafe extern "C" fn(klass: *mut ObjectCl= ass, data: *mut c_void)> =3D Some(dummy_class_init); const CLASS_BASE_INIT: Option< --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733748581; cv=none; d=zohomail.com; s=zohoarc; b=bmo4gUVYk551sz3VCGOwes2j54K7xCYWhJc/GLc8LYz5uYMYIM6rXdCQ9xsnCDBfkzc3BqhjIFkW9uAGy47qh3Bx18Wc0uMy3I4D+6EU6QgohfaE8RqmOAYQJ3w6vVrGK8wVeBDTQzSrCBNZ/PC0MCWdb2/NYs1qTYMCF6hXkW4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733748580; 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=3KnA6nxj6wRieH/eonLUIy1D83UK4FyVWaqyO6ZnPKE=; b=DESz9+iWS/M0Ux1vJskikM/M8dAkYe6JlyvHOZjQEa7gZltNqaCDLsOVXkNlVua292Qt818c4JqZxy0MbqNRX2YHPyocx9hbnvUuZDBiicI7wlSZG+9POpGSGYjBf4JgzQKjmnEfwEkevT5PE/LVYPqEBB8iHC1EV1ugTohEpB4= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733748580536580.9446472358993; Mon, 9 Dec 2024 04:49:40 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd1Q-0003wf-5t; Mon, 09 Dec 2024 07:37:56 -0500 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 <pbonzini@redhat.com>) id 1tKd1O-0003vN-AT for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:54 -0500 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 <pbonzini@redhat.com>) id 1tKd1M-0007RP-An for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:53 -0500 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-178-5c8j9pdjN1ugjvp4kixtPA-1; Mon, 09 Dec 2024 07:37:45 -0500 Received: by mail-wm1-f72.google.com with SMTP id 5b1f17b1804b1-434fe2b605eso2636015e9.2 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:37:45 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-434f7160599sm43836515e9.23.2024.12.09.04.37.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:37:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747867; 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=3KnA6nxj6wRieH/eonLUIy1D83UK4FyVWaqyO6ZnPKE=; b=dD2I905alHuZIa0spzNH5tDj3kw3lfegu2KN46OV83FDi7H3X2G/1VrZS+RYtTgF0hAP08 HPoKjX8MhnEw5liiFXOVZQZUzhZKRE8CtbaVBkgjNg6e21aNeXu15cgtUR6XuVwHcExhLm /h4cXPjfyi6KjK3X9pIhZCNa4EIffEg= X-MC-Unique: 5c8j9pdjN1ugjvp4kixtPA-1 X-Mimecast-MFC-AGG-ID: 5c8j9pdjN1ugjvp4kixtPA X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747864; x=1734352664; 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=3KnA6nxj6wRieH/eonLUIy1D83UK4FyVWaqyO6ZnPKE=; b=OqCJXrvJ9iQOJBA01VlOZfgWm8H7lwZi8T8P4CseJ00A+lsH4qoYjfXJUfHe5hGCEQ LLVysGzMyjATgvhaHpyFMqnj3qn9O4hvkfzUadbIZOROZ0yZOxeZ+MFjtXI9QYQUD/Dq D6VcbYnHKrDL4ZsYgVyRg8XH4k/SKYOeGGYONbV7VckaNEExWurWEY7+lKObfXx3LUgQ aGHZHVNqxuM6mOWJwVRt3SOGrog9Z+hn6/3cqHK4COYlZKhH7H4OLd+7QPikYISJ0KVH vzvWCvRnWZzfQzo76Zzsiv93zC1R9IyV5FBHy21RCJ9HKP1oVVkYabK+GtDle5bZj5a+ A2iA== X-Gm-Message-State: AOJu0YwxS/ETdZmYwGbQ67+nEqFWlohLYOpLwdtmjUP7TfKiYMi8UMGL PlE/kHC+/V3i0RCI1xXKT0kx/EuPZ9CiLbyu5ygPDfQQQ6eIafvE4A2/CF+CaaeD65V4yZCrVuW uiD+hYoSg2PeHjWJAxbVz8dSJQ8nPQduhy3qHsk551uqn2/2OlCEkmnPFJASi3lOAXfaQVR8mWD BtXYAFY8EPNf/xGyXXnHrPitb5ee4nhZzks9sh X-Gm-Gg: ASbGncuGgqjLQScWXPimMER25O84riVzlfRO6zAmHhvdFWfe0AvWiQquvWZN2LhZBWe cu8+h5sTQVo0V+piOIAr9umZSuSaR/qUIa0lqwVp4X0EXk+z1YarL8eliojLzNb9e15oPbxyzS8 L+/nplN8mHEPUSQL/HxuNf9pYRwc4BJyQyaQcGXjYnoJ6TInTHs7hKx3KambPtNPW7iq9i798rO T7UBZZOuNncQDPkqbeNOlWEUhScNUpz4uxodQSDeO9E+UGQfiXt9A== X-Received: by 2002:a05:600c:4447:b0:431:5863:4240 with SMTP id 5b1f17b1804b1-434fffa2a31mr2416485e9.24.1733747862537; Mon, 09 Dec 2024 04:37:42 -0800 (PST) X-Google-Smtp-Source: AGHT+IEEAVQBoTp9SPcNz6rRg1uImK74hwNwwXWayI3C2hJkGn6J5hBPTMiDx3R2ecMnTcnDOHcz/g== X-Received: by 2002:a05:600c:4447:b0:431:5863:4240 with SMTP id 5b1f17b1804b1-434fffa2a31mr2416285e9.24.1733747862149; Mon, 09 Dec 2024 04:37:42 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 09/26] rust: qom: convert type_info! macro to an associated const Date: Mon, 9 Dec 2024 13:37:00 +0100 Message-ID: <20241209123717.99077-10-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733748583035116600 Content-Type: text/plain; charset="utf-8" type_info! is only used in the definition of ObjectImpl::TYPE_INFO, and in fact in all of them. Pull type_info!'s definition into the ObjectImpl trait, thus simplifying the external interface of qemu_api::definitions. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Zhao Liu <zhao1.liu@intel.com> --- rust/hw/char/pl011/src/device.rs | 6 ++-- rust/qemu-api/src/definitions.rs | 50 ++++++++++++++------------------ rust/qemu-api/tests/tests.rs | 1 - 3 files changed, 24 insertions(+), 33 deletions(-) diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index bd12067aaf0..bcb146c24d6 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -106,7 +106,6 @@ pub struct PL011State { =20 impl ObjectImpl for PL011State { type Class =3D PL011Class; - const TYPE_INFO: qemu_api::bindings::TypeInfo =3D qemu_api::type_info!= { Self }; const TYPE_NAME: &'static CStr =3D crate::TYPE_PL011; const PARENT_TYPE_NAME: Option<&'static CStr> =3D Some(TYPE_SYS_BUS_DE= VICE); const INSTANCE_INIT: Option<unsafe extern "C" fn(obj: *mut Object)> = =3D Some(pl011_init); @@ -149,7 +148,7 @@ unsafe fn init(&mut self) { addr_of_mut!(*self).cast::<Object>(), &PL011_OPS, addr_of_mut!(*self).cast::<c_void>(), - Self::TYPE_INFO.name, + Self::TYPE_NAME.as_ptr(), 0x1000, ); sysbus_init_mmio(sbd, addr_of_mut!(self.iomem)); @@ -598,7 +597,7 @@ pub fn post_load(&mut self, _version_id: u32) -> Result= <(), ()> { chr: *mut Chardev, ) -> *mut DeviceState { unsafe { - let dev: *mut DeviceState =3D qdev_new(PL011State::TYPE_INFO.name); + let dev: *mut DeviceState =3D qdev_new(PL011State::TYPE_NAME.as_pt= r()); let sysbus: *mut SysBusDevice =3D dev.cast::<SysBusDevice>(); =20 qdev_prop_set_chr(dev, c_str!("chardev").as_ptr(), chr); @@ -660,7 +659,6 @@ impl qemu_api::definitions::ClassInitImpl for PL011Lumi= naryClass { =20 impl ObjectImpl for PL011Luminary { type Class =3D PL011LuminaryClass; - const TYPE_INFO: qemu_api::bindings::TypeInfo =3D qemu_api::type_info!= { Self }; const TYPE_NAME: &'static CStr =3D crate::TYPE_PL011_LUMINARY; const PARENT_TYPE_NAME: Option<&'static CStr> =3D Some(crate::TYPE_PL0= 11); const INSTANCE_INIT: Option<unsafe extern "C" fn(obj: *mut Object)> = =3D Some(pl011_luminary_init); diff --git a/rust/qemu-api/src/definitions.rs b/rust/qemu-api/src/definitio= ns.rs index 3291f4242ce..6ecfaf51b09 100644 --- a/rust/qemu-api/src/definitions.rs +++ b/rust/qemu-api/src/definitions.rs @@ -9,15 +9,34 @@ use crate::bindings::{Object, ObjectClass, TypeInfo}; =20 /// Trait a type must implement to be registered with QEMU. -pub trait ObjectImpl { - type Class; - const TYPE_INFO: TypeInfo; +pub trait ObjectImpl: Sized { + type Class: ClassInitImpl; const TYPE_NAME: &'static CStr; const PARENT_TYPE_NAME: Option<&'static CStr>; const ABSTRACT: bool =3D false; const INSTANCE_INIT: Option<unsafe extern "C" fn(obj: *mut Object)> = =3D None; const INSTANCE_POST_INIT: Option<unsafe extern "C" fn(obj: *mut Object= )> =3D None; const INSTANCE_FINALIZE: Option<unsafe extern "C" fn(obj: *mut Object)= > =3D None; + + const TYPE_INFO: TypeInfo =3D TypeInfo { + name: Self::TYPE_NAME.as_ptr(), + parent: if let Some(pname) =3D Self::PARENT_TYPE_NAME { + pname.as_ptr() + } else { + core::ptr::null_mut() + }, + instance_size: core::mem::size_of::<Self>(), + instance_align: core::mem::align_of::<Self>(), + instance_init: Self::INSTANCE_INIT, + instance_post_init: Self::INSTANCE_POST_INIT, + instance_finalize: Self::INSTANCE_FINALIZE, + abstract_: Self::ABSTRACT, + class_size: core::mem::size_of::<Self::Class>(), + class_init: <Self::Class as ClassInitImpl>::CLASS_INIT, + class_base_init: <Self::Class as ClassInitImpl>::CLASS_BASE_INIT, + class_data: core::ptr::null_mut(), + interfaces: core::ptr::null_mut(), + }; } =20 /// Trait used to fill in a class struct. @@ -83,28 +102,3 @@ extern "C" fn ctor_fn() { } }; } - -#[macro_export] -macro_rules! type_info { - ($t:ty) =3D> { - $crate::bindings::TypeInfo { - name: <$t as $crate::definitions::ObjectImpl>::TYPE_NAME.as_pt= r(), - parent: if let Some(pname) =3D <$t as $crate::definitions::Obj= ectImpl>::PARENT_TYPE_NAME { - pname.as_ptr() - } else { - ::core::ptr::null_mut() - }, - instance_size: ::core::mem::size_of::<$t>(), - instance_align: ::core::mem::align_of::<$t>(), - instance_init: <$t as $crate::definitions::ObjectImpl>::INSTAN= CE_INIT, - instance_post_init: <$t as $crate::definitions::ObjectImpl>::I= NSTANCE_POST_INIT, - instance_finalize: <$t as $crate::definitions::ObjectImpl>::IN= STANCE_FINALIZE, - abstract_: <$t as $crate::definitions::ObjectImpl>::ABSTRACT, - class_size: ::core::mem::size_of::<<$t as $crate::definitions= ::ObjectImpl>::Class>(), - class_init: <<$t as $crate::definitions::ObjectImpl>::Class as= $crate::definitions::ClassInitImpl>::CLASS_INIT, - class_base_init: <<$t as $crate::definitions::ObjectImpl>::Cla= ss as $crate::definitions::ClassInitImpl>::CLASS_BASE_INIT, - class_data: ::core::ptr::null_mut(), - interfaces: ::core::ptr::null_mut(), - }; - } -} diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index 704c63c846f..7f9df348b00 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -55,7 +55,6 @@ pub struct DummyClass { =20 impl ObjectImpl for DummyState { type Class =3D DummyClass; - const TYPE_INFO: qemu_api::bindings::TypeInfo =3D qemu_api::type_i= nfo! { Self }; const TYPE_NAME: &'static CStr =3D c_str!("dummy"); const PARENT_TYPE_NAME: Option<&'static CStr> =3D Some(device_clas= s::TYPE_DEVICE); } --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733748319; cv=none; d=zohomail.com; s=zohoarc; b=jUp0ge4vr6yaZP1573Z3qJXagZ4zKgMbcfe2qHE8Z+OfQbi5VYTx/vxtj0pTjvOLZ4xE0FJ7FHdMGIvM5gI+Jo1IWTPeVspLMCM/K9O+AD7XMKKOjGYKmsdEhYI02tx66eztRtZJ3m15r7mTA/PkoPlsDq6QCG01bV4nVRRkkAY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733748319; 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=rnI0niveAFX2WdKfqxklK+1Zt06kPSFJCN7eFa7HF+8=; b=HNH5/0tuSk4oxlcFcMx6QenOzY4MPdIe35knaw3UlQ9GCFNgSzYMyiayoKQA11ZkqJFQGH7XoX7csYqwaMvTfa0BcsoEg8CqQouj4nJ/V27khpCQZ5utLfErhUWcrgIbTwHnpFGGUtbcOfNeOGgAG6ocMVnPII1lePwh62b+DQA= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733748319301211.670314221; Mon, 9 Dec 2024 04:45:19 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd1S-0003y9-Bw; Mon, 09 Dec 2024 07:37:58 -0500 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 <pbonzini@redhat.com>) id 1tKd1P-0003wd-R5 for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:56 -0500 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 <pbonzini@redhat.com>) id 1tKd1M-0007Ra-Br for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:55 -0500 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-353-gHA1aVjTO12IlGRPdoVo3w-1; Mon, 09 Dec 2024 07:37:46 -0500 Received: by mail-wr1-f70.google.com with SMTP id ffacd0b85a97d-385d51ba2f5so1655300f8f.2 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:37:46 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3861ecf40a0sm12875064f8f.13.2024.12.09.04.37.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:37:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747867; 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=rnI0niveAFX2WdKfqxklK+1Zt06kPSFJCN7eFa7HF+8=; b=JKKeKJDr/MFU5pmOM9Yhn5rhxjOrLv/dTkwB0fp3e8KSqtYbXgClDWxibz4q20Ak9Nksg9 9pKGqY2CiTNB56i47inSReccjtPy9PumrkQPVX+feXejOaTU7aG3lm9NdeZa8wnpklTLCW 6/i1KIuLpISKzbNqcX70HiGB8ZyeMb8= X-MC-Unique: gHA1aVjTO12IlGRPdoVo3w-1 X-Mimecast-MFC-AGG-ID: gHA1aVjTO12IlGRPdoVo3w X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747864; x=1734352664; 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=rnI0niveAFX2WdKfqxklK+1Zt06kPSFJCN7eFa7HF+8=; b=W/OEzT58pqLF7jDFiZb3jPUgCCtw+H4n84dn3hG0aSs6D239Jjx6K/Kxj8ffHpcvrp y9tPHTEMB+Z2IwYj7mzHlDtNUOFVQdedwPVOF9S4Lg7keNvRHUs9Uh3BFPWTAjgSJj2o nM63/ehtpfasiPnLd7vhBX8PgquFZ9VpTALmR+uW8v9IhPRq/j/A94642k0BZTYfriR2 /TFlnHPICRF20F9fwXb/+z3cW0gwsJ2RGjc9snfpAgfaxOg7fAAauWkV2zWXdz710qco PQDvCFQc6z1mGfeNDCE3+LHlVCbA42S9JEc0rL6Rv3vrXhrzJs0n+JqV90LNq5VcUj+s LqoA== X-Gm-Message-State: AOJu0YxI815ZAFO8RsCiW7fJ0/z+toetuTDwDXoZwyQsP/6+ml8IJiUl AMF7H1AUtnIbKokolJ+sDOPVaNW72514S9TVI0fWzD5j8aY2B5ZNedcCTvPeZe2WTe345ve6P2s Ns1gZednnKHCzuOxwmjfPZXk3lTQT5bphrSoIOe2S7hBvb4GKxMb6WGt6hLpaYd4h3CNtCrHVAd UEc3T47kT0pKNYqBqh6ZSbIqfCsaZtpmvydu98 X-Gm-Gg: ASbGncsXZJRsWJm2J6tnf4T8yWQrL7Otq4ZI5u9ofe7iyE6yEPu6hLbjDFfCBZSogoN L88xWe/CCiMRFdzmR+huoCCTRshHEiiQJGgTzbIbeZ2tv/tINV3XFqpSqw/nJ7rzHSJ2wnDcpQO D9MJmsrZFpbG++sk7bHkJDKkRN1KLjmck1j/D5IBTDgZJdKcC/nBPG8ra5W2zxXOkiEDUK+SdO5 w/xuHj7qgIgyambsS7jQqPPYsN7manXBH5KT2hyNMB1r+fbVKcDyQ== X-Received: by 2002:a5d:6c69:0:b0:385:e013:39ec with SMTP id ffacd0b85a97d-3862b33f0d1mr9303165f8f.8.1733747864322; Mon, 09 Dec 2024 04:37:44 -0800 (PST) X-Google-Smtp-Source: AGHT+IEaI5mpcGtPfQA/5tjvnqn4QZw2Pce8+RV3HgH+A6JNVqnFNEEY9kcB0+Ainpq7S21I/hgG8A== X-Received: by 2002:a5d:6c69:0:b0:385:e013:39ec with SMTP id ffacd0b85a97d-3862b33f0d1mr9303141f8f.8.1733747863883; Mon, 09 Dec 2024 04:37:43 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 10/26] rust: qom: move ClassInitImpl to the instance side Date: Mon, 9 Dec 2024 13:37:01 +0100 Message-ID: <20241209123717.99077-11-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733748319738116600 Content-Type: text/plain; charset="utf-8" Put all traits on the instance struct, which makes it possible to reuse class structs if no new virtual methods or class fields are added. This is almost always the case for devices (because they are leaf classes), which is the primary use case for Rust. This is also simpler: soon we will find the implemented methods without macros, and this removes the need to go from the class struct to the instance struct to find the implementation of the *Impl traits. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Zhao Liu <zhao1.liu@intel.com> --- rust/hw/char/pl011/src/device.rs | 4 ++-- rust/qemu-api/src/definitions.rs | 8 ++++---- rust/qemu-api/tests/tests.rs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index bcb146c24d6..2384d4bcb95 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -116,7 +116,7 @@ pub struct PL011Class { _inner: [u8; 0], } =20 -impl qemu_api::definitions::ClassInitImpl for PL011Class { +impl qemu_api::definitions::ClassInitImpl for PL011State { const CLASS_INIT: Option<unsafe extern "C" fn(klass: *mut ObjectClass,= data: *mut c_void)> =3D Some(crate::device_class::pl011_class_init); const CLASS_BASE_INIT: Option< @@ -649,7 +649,7 @@ pub struct PL011LuminaryClass { } } =20 -impl qemu_api::definitions::ClassInitImpl for PL011LuminaryClass { +impl qemu_api::definitions::ClassInitImpl for PL011Luminary { const CLASS_INIT: Option<unsafe extern "C" fn(klass: *mut ObjectClass,= data: *mut c_void)> =3D None; const CLASS_BASE_INIT: Option< diff --git a/rust/qemu-api/src/definitions.rs b/rust/qemu-api/src/definitio= ns.rs index 6ecfaf51b09..487712611f6 100644 --- a/rust/qemu-api/src/definitions.rs +++ b/rust/qemu-api/src/definitions.rs @@ -9,8 +9,8 @@ use crate::bindings::{Object, ObjectClass, TypeInfo}; =20 /// Trait a type must implement to be registered with QEMU. -pub trait ObjectImpl: Sized { - type Class: ClassInitImpl; +pub trait ObjectImpl: ClassInitImpl + Sized { + type Class; const TYPE_NAME: &'static CStr; const PARENT_TYPE_NAME: Option<&'static CStr>; const ABSTRACT: bool =3D false; @@ -32,8 +32,8 @@ pub trait ObjectImpl: Sized { instance_finalize: Self::INSTANCE_FINALIZE, abstract_: Self::ABSTRACT, class_size: core::mem::size_of::<Self::Class>(), - class_init: <Self::Class as ClassInitImpl>::CLASS_INIT, - class_base_init: <Self::Class as ClassInitImpl>::CLASS_BASE_INIT, + class_init: <Self as ClassInitImpl>::CLASS_INIT, + class_base_init: <Self as ClassInitImpl>::CLASS_BASE_INIT, class_data: core::ptr::null_mut(), interfaces: core::ptr::null_mut(), }; diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index 7f9df348b00..fd0c979121c 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -59,7 +59,7 @@ impl ObjectImpl for DummyState { const PARENT_TYPE_NAME: Option<&'static CStr> =3D Some(device_clas= s::TYPE_DEVICE); } =20 - impl ClassInitImpl for DummyClass { + impl ClassInitImpl for DummyState { const CLASS_INIT: Option<unsafe extern "C" fn(klass: *mut ObjectCl= ass, data: *mut c_void)> =3D Some(dummy_class_init); const CLASS_BASE_INIT: Option< --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733748016; cv=none; d=zohomail.com; s=zohoarc; b=S1jxC7vflb+fqMR4dauzAMBnPUn5y5MNDQF47FVIxb9zvfccRbKFAlGfzSos/b+P+Adl7JgmaAG7swgQ7MGeMkxIvKXM6HJvt9sbKpZqQ9RTxJXtFnEAb985YUe3ikHwhvxVoo6hBDE4n3m6b7284yxV591IipRPUjKBqECsAXM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733748016; 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=dUpcjFB07jJVa4XSFzhd/IiH28exWmu8j4Bb3GB+WDw=; b=KNEjsWr8PT2UykxF1wPfkfVBYxl/dSSrsP98ipvkGAyBLUUJTuIfmBK4787A64fo1V2jQbXa6wmTsUxC6IQnqjn5rNbJPDNqK+cT7Piv+ZOPS9g2sRgxyozh32DN4Xc9cgegFJEYL/2oa1iGin86VIcdUwTIRGh/YWfmfWnbv7Y= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733748016751901.0583454891452; Mon, 9 Dec 2024 04:40:16 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd2j-0004kq-Ks; Mon, 09 Dec 2024 07:39:19 -0500 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 <pbonzini@redhat.com>) id 1tKd1Q-0003wx-9o for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:56 -0500 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 <pbonzini@redhat.com>) id 1tKd1M-0007S0-CQ for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:55 -0500 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-681-xVkBYPq4NWG0JdE97xe4Lw-1; Mon, 09 Dec 2024 07:37:49 -0500 Received: by mail-wm1-f69.google.com with SMTP id 5b1f17b1804b1-434f5b7b4a2so9343745e9.0 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:37:49 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-434ea1ae415sm82976755e9.33.2024.12.09.04.37.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:37:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747870; 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=dUpcjFB07jJVa4XSFzhd/IiH28exWmu8j4Bb3GB+WDw=; b=Uo7LuefCq+0lPb/LawCUDN+0qDnxE1chP0p7ojiNdCT520UKa2n+A3NuQzTKvQ+F1VZbrq 6NMH1rmOspk1koPhrycc2YdBPVLR/VrpI5oFyKLcf2/9Z6S+UkIaEha24OuWrJfT1/o3PP 1VtP/hzpkaoNvt1Ga7Qi6nSdEERiHj8= X-MC-Unique: xVkBYPq4NWG0JdE97xe4Lw-1 X-Mimecast-MFC-AGG-ID: xVkBYPq4NWG0JdE97xe4Lw X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747867; x=1734352667; 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=dUpcjFB07jJVa4XSFzhd/IiH28exWmu8j4Bb3GB+WDw=; b=pylIRHXqwOWOUd0OVOb59ksz6hEw17qQXvr6z5s7fv5TeAmgiSXlwM8a/1eqrw9qBV Wabg803mRfpfLAa2BbnbI8f53URvXrZSvRMtOOc1YouDolv3DQGDlsWf3tLIpxVjDYpM MJ1CMHyP4nWnmkOaFXqpLc3hzjh8tORFa66GigKVfZ8bUC01utJZ3/kxiC/dCb7bnAwt Auwmnw0pwi5SRu9SwDSjzGaPwzCwq0OjNWwSaBHLIKQUOYh0sQwO6PpWCAEWdkExEOJ9 thc6XiZzPqQS5DTuio6bEi2g/fQNVzT3LKhzUl7CKOwswRcKfF/x/LiUiKThmj9XfEDA XGVA== X-Gm-Message-State: AOJu0Yw8DysR7l2AvMyP2/cPwEJTNr0HQq45uKpkTepyCIMzXT/Vusss vZVmnz7z1NEFlwTz+wbj1emDIjADehDokUiLmPvLAL7Cn8IYzONtmozQXfvEjyixba6fTOOshDr +uqPHmTiKBSjbWohk8LGLM48iuZXYimCSG6IHsZXlZ41rYqM6YJDGUObVSzPRUXO6SRGAGF+/WH kBqx/QN2b5k8aV1J/QTmJImeGiJBuF1fMO8o9w X-Gm-Gg: ASbGnctMbjlxR+tzZymShoWxq1JlSuU8h379CQ312CR7r+HnAz9bm10+zaNvHokmosG A4Nk6OdGkg5E9VpS0Jv98l0OsVJwSwqjI5aDITnd9TX9W1ncY41BUSLEEMh2n89Xj/lOSkmE7HG vf4IEepAbVy0g95AWjk0d0DyZ9mzetw71gm/C44BixPFiepmOEXM7yJjEMx8S9W0MrH543+xsH8 kTzAmAfaAYvT9VhvhryaqtNyEPY89DGjwir4/QU0Dsr0Ofgp8fIJA== X-Received: by 2002:a05:600c:3550:b0:434:e9ee:c2d with SMTP id 5b1f17b1804b1-434fff9c1femr2317905e9.26.1733747867094; Mon, 09 Dec 2024 04:37:47 -0800 (PST) X-Google-Smtp-Source: AGHT+IEjB6e+Wg3uC2Gu/Ao4y0rgxEjkl/WZ+bdpEsGWQg1pkCV7rgfFy9Vi+GICVUc7VCyEUYSnYA== X-Received: by 2002:a05:600c:3550:b0:434:e9ee:c2d with SMTP id 5b1f17b1804b1-434fff9c1femr2317715e9.26.1733747866665; Mon, 09 Dec 2024 04:37:46 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 11/26] rust: qdev: move device_class_init! body to generic function, ClassInitImpl implementation to macro Date: Mon, 9 Dec 2024 13:37:02 +0100 Message-ID: <20241209123717.99077-12-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733748018456116600 Content-Type: text/plain; charset="utf-8" Use a trait to access the former parameters to device_class_init!. This allows hiding the details of the class_init implementation behind a generic function and makes higher-level functionality available from qemu_api. The implementation of ClassInitImpl is then the same for all devices and is easily macroized. Later on, we can remove the need to implement ClassInitImpl by hand for all device types, and stop making rust_device_class_init<>() public. While at it, document the members of DeviceImpl. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- rust/hw/char/pl011/src/device.rs | 34 +++++----- rust/hw/char/pl011/src/device_class.rs | 8 --- rust/qemu-api/src/device_class.rs | 87 +++++++++++++++++++++----- rust/qemu-api/tests/tests.rs | 30 ++++----- 4 files changed, 103 insertions(+), 56 deletions(-) diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index 2384d4bcb95..28b1924337d 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -12,11 +12,13 @@ bindings::{self, *}, c_str, definitions::ObjectImpl, - device_class::TYPE_SYS_BUS_DEVICE, + device_class::{DeviceImpl, TYPE_SYS_BUS_DEVICE}, + impl_device_class, irq::InterruptSource, }; =20 use crate::{ + device_class, memory_ops::PL011_OPS, registers::{self, Interrupt}, RegisterOffset, @@ -116,14 +118,20 @@ pub struct PL011Class { _inner: [u8; 0], } =20 -impl qemu_api::definitions::ClassInitImpl for PL011State { - const CLASS_INIT: Option<unsafe extern "C" fn(klass: *mut ObjectClass,= data: *mut c_void)> =3D - Some(crate::device_class::pl011_class_init); - const CLASS_BASE_INIT: Option< - unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void), - > =3D None; +impl DeviceImpl for PL011State { + fn properties() -> &'static [Property] { + &device_class::PL011_PROPERTIES + } + fn vmsd() -> Option<&'static VMStateDescription> { + Some(&device_class::VMSTATE_PL011) + } + const REALIZE: Option<unsafe extern "C" fn(*mut DeviceState, *mut *mut= Error)> =3D + Some(device_class::pl011_realize); + const RESET: Option<unsafe extern "C" fn(*mut DeviceState)> =3D Some(d= evice_class::pl011_reset); } =20 +impl_device_class!(PL011State); + impl PL011State { /// Initializes a pre-allocated, unitialized instance of `PL011State`. /// @@ -649,17 +657,13 @@ pub struct PL011LuminaryClass { } } =20 -impl qemu_api::definitions::ClassInitImpl for PL011Luminary { - const CLASS_INIT: Option<unsafe extern "C" fn(klass: *mut ObjectClass,= data: *mut c_void)> =3D - None; - const CLASS_BASE_INIT: Option< - unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void), - > =3D None; -} - impl ObjectImpl for PL011Luminary { type Class =3D PL011LuminaryClass; const TYPE_NAME: &'static CStr =3D crate::TYPE_PL011_LUMINARY; const PARENT_TYPE_NAME: Option<&'static CStr> =3D Some(crate::TYPE_PL0= 11); const INSTANCE_INIT: Option<unsafe extern "C" fn(obj: *mut Object)> = =3D Some(pl011_luminary_init); } + +impl DeviceImpl for PL011Luminary {} + +impl_device_class!(PL011Luminary); diff --git a/rust/hw/char/pl011/src/device_class.rs b/rust/hw/char/pl011/sr= c/device_class.rs index a707fde1384..c61b6bb0258 100644 --- a/rust/hw/char/pl011/src/device_class.rs +++ b/rust/hw/char/pl011/src/device_class.rs @@ -93,14 +93,6 @@ extern "C" fn pl011_post_load(opaque: *mut c_void, versi= on_id: c_int) -> c_int { ), } =20 -qemu_api::device_class_init! { - pl011_class_init, - props =3D> PL011_PROPERTIES, - realize_fn =3D> Some(pl011_realize), - legacy_reset_fn =3D> Some(pl011_reset), - vmsd =3D> VMSTATE_PL011, -} - /// # Safety /// /// We expect the FFI user of this function to pass a valid pointer, that = has diff --git a/rust/qemu-api/src/device_class.rs b/rust/qemu-api/src/device_c= lass.rs index 922bbce1bb8..f683f94f2a5 100644 --- a/rust/qemu-api/src/device_class.rs +++ b/rust/qemu-api/src/device_class.rs @@ -2,25 +2,80 @@ // Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org> // SPDX-License-Identifier: GPL-2.0-or-later =20 -use std::ffi::CStr; +use std::{ffi::CStr, os::raw::c_void}; =20 -use crate::bindings; +use crate::{ + bindings::{self, DeviceClass, DeviceState, Error, ObjectClass, Propert= y, VMStateDescription}, + zeroable::Zeroable, +}; + +/// Trait providing the contents of [`DeviceClass`]. +pub trait DeviceImpl { + /// _Realization_ is the second stage of device creation. It contains + /// all operations that depend on device properties and can fail (note: + /// this is not yet supported for Rust devices). + /// + /// If not `None`, the parent class's `realize` method is overridden + /// with the function pointed to by `REALIZE`. + const REALIZE: Option<unsafe extern "C" fn(*mut DeviceState, *mut *mut= Error)> =3D None; + + /// If not `None`, the parent class's `reset` method is overridden + /// with the function pointed to by `RESET`. + /// + /// Rust does not yet support the three-phase reset protocol; this is + /// usually okay for leaf classes. + const RESET: Option<unsafe extern "C" fn(dev: *mut DeviceState)> =3D N= one; + + /// An array providing the properties that the user can set on the + /// device. Not a `const` because referencing statics in constants + /// is unstable until Rust 1.83.0. + fn properties() -> &'static [Property] { + &[Zeroable::ZERO; 1] + } + + /// A `VMStateDescription` providing the migration format for the devi= ce + /// Not a `const` because referencing statics in constants is unstable + /// until Rust 1.83.0. + fn vmsd() -> Option<&'static VMStateDescription> { + None + } +} + +/// # Safety +/// +/// We expect the FFI user of this function to pass a valid pointer that +/// can be downcasted to type `DeviceClass`, because `T` implements +/// `DeviceImpl`. +pub unsafe extern "C" fn rust_device_class_init<T: DeviceImpl>( + klass: *mut ObjectClass, + _: *mut c_void, +) { + let mut dc =3D ::core::ptr::NonNull::new(klass.cast::<DeviceClass>()).= unwrap(); + unsafe { + let dc =3D dc.as_mut(); + if let Some(realize_fn) =3D <T as DeviceImpl>::REALIZE { + dc.realize =3D Some(realize_fn); + } + if let Some(reset_fn) =3D <T as DeviceImpl>::RESET { + bindings::device_class_set_legacy_reset(dc, Some(reset_fn)); + } + if let Some(vmsd) =3D <T as DeviceImpl>::vmsd() { + dc.vmsd =3D vmsd; + } + bindings::device_class_set_props(dc, <T as DeviceImpl>::properties= ().as_ptr()); + } +} =20 #[macro_export] -macro_rules! device_class_init { - ($func:ident, props =3D> $props:ident, realize_fn =3D> $realize_fn:exp= r, legacy_reset_fn =3D> $legacy_reset_fn:expr, vmsd =3D> $vmsd:ident$(,)*) = =3D> { - pub unsafe extern "C" fn $func( - klass: *mut $crate::bindings::ObjectClass, - _: *mut ::std::os::raw::c_void, - ) { - let mut dc =3D - ::core::ptr::NonNull::new(klass.cast::<$crate::bindings::D= eviceClass>()).unwrap(); - unsafe { - dc.as_mut().realize =3D $realize_fn; - dc.as_mut().vmsd =3D &$vmsd; - $crate::bindings::device_class_set_legacy_reset(dc.as_mut(= ), $legacy_reset_fn); - $crate::bindings::device_class_set_props(dc.as_mut(), $pro= ps.as_ptr()); - } +macro_rules! impl_device_class { + ($type:ty) =3D> { + impl $crate::definitions::ClassInitImpl for $type { + const CLASS_INIT: Option< + unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut := :std::os::raw::c_void), + > =3D Some($crate::device_class::rust_device_class_init::<$typ= e>); + const CLASS_BASE_INIT: Option< + unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut := :std::os::raw::c_void), + > =3D None; } }; } diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index fd0c979121c..b8b12a40422 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -2,13 +2,14 @@ // Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org> // SPDX-License-Identifier: GPL-2.0-or-later =20 -use std::{ffi::CStr, os::raw::c_void}; +use std::ffi::CStr; =20 use qemu_api::{ bindings::*, c_str, declare_properties, define_property, - definitions::{ClassInitImpl, ObjectImpl}, - device_class, device_class_init, + definitions::ObjectImpl, + device_class::{self, DeviceImpl}, + impl_device_class, zeroable::Zeroable, }; =20 @@ -45,28 +46,23 @@ pub struct DummyClass { ), } =20 - device_class_init! { - dummy_class_init, - props =3D> DUMMY_PROPERTIES, - realize_fn =3D> None, - legacy_reset_fn =3D> None, - vmsd =3D> VMSTATE, - } - impl ObjectImpl for DummyState { type Class =3D DummyClass; const TYPE_NAME: &'static CStr =3D c_str!("dummy"); const PARENT_TYPE_NAME: Option<&'static CStr> =3D Some(device_clas= s::TYPE_DEVICE); } =20 - impl ClassInitImpl for DummyState { - const CLASS_INIT: Option<unsafe extern "C" fn(klass: *mut ObjectCl= ass, data: *mut c_void)> =3D - Some(dummy_class_init); - const CLASS_BASE_INIT: Option< - unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_voi= d), - > =3D None; + impl DeviceImpl for DummyState { + fn properties() -> &'static [Property] { + &DUMMY_PROPERTIES + } + fn vmsd() -> Option<&'static VMStateDescription> { + Some(&VMSTATE) + } } =20 + impl_device_class!(DummyState); + unsafe { module_call_init(module_init_type::MODULE_INIT_QOM); object_unref(object_new(DummyState::TYPE_NAME.as_ptr()).cast()); --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733748761; cv=none; d=zohomail.com; s=zohoarc; b=G48pvmYsTvLq0xRoR/rp51TUPuGGu4UhK83k06SI30bbkPqNPlDK+Q2MlTa2VsRCVoZ2AeY4pJKwGjVUP4/O6Lq2TDu9/fgq8jsY0CjPQRLf9DD44edculOBIugdDBT66NKxPo2hMwR12oeokyIy1NAHmIG1QGaFQpEYzZci4N8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733748761; 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=S2XjECiQ3aF3ccKlQ+UfpX2Co0fO2a2DC8TPDve57ok=; b=mJcw2sYj9v6KMvb8Yqa860wFNI/CyQFa6+jlWTFHycDEtvwbdzChv6DTtRKs0ux8b6dy5Vv4hOHYCkFQwJv+xpqSHTVv8SXyJOFV/3CVfIRJd0LWmYjgJUqQ0MmKda724laQoMmM4MAmPeUgnPIZ5/B0FgT0AqkRqmw2PMxiSag= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 173374876136446.32941243908999; Mon, 9 Dec 2024 04:52:41 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd41-0006AI-RH; Mon, 09 Dec 2024 07:40:40 -0500 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 <pbonzini@redhat.com>) id 1tKd1U-00040L-T4 for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:00 -0500 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 <pbonzini@redhat.com>) id 1tKd1N-0007Sm-HR for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:00 -0500 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-369-EhQXVIm6PzWkeJjUBnWreQ-1; Mon, 09 Dec 2024 07:37:51 -0500 Received: by mail-wr1-f70.google.com with SMTP id ffacd0b85a97d-385ded5e92aso1658533f8f.3 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:37:51 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3863157fb80sm8857813f8f.19.2024.12.09.04.37.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:37:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747872; 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=S2XjECiQ3aF3ccKlQ+UfpX2Co0fO2a2DC8TPDve57ok=; b=H9m1vDyYUEtqLUXB9SVyKbkliRvwnxndbRUdmZRsERqV1dkvzaWFs3Mt140QOX8Uk8Am65 QKzdhKHCxH7qWBc87pymXoPUWg2NRTgGx1skuwdgl5lOVvCjY/wsXw4Ks0K+v/NmIJ4Qd/ VXjjFR1wsAgX7GZ2ZeKlYQYkn8nnmWU= X-MC-Unique: EhQXVIm6PzWkeJjUBnWreQ-1 X-Mimecast-MFC-AGG-ID: EhQXVIm6PzWkeJjUBnWreQ X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747869; x=1734352669; 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=S2XjECiQ3aF3ccKlQ+UfpX2Co0fO2a2DC8TPDve57ok=; b=YhKAJOMzKTBxTn0NrwPdAkWt986JK+3pX0k3VRA3mzjFwwF6sBnU1nhi1975QJZvtQ m2Q88oRMH8P4jnHEEJ/snis2vFXxavgaQcU3sw0WZkahwoT4/2YixHNuFAjyd1QoPjL+ Rcx/3FD3Wq/o5ZEQ7QFwb6GviYESJZZORc+DEaqAdtcAJDM23fs8vzlhqqVLBUS2odXz R1H2GyDPWAh+ImDGrNqHqaccNay0S9cpWBRlXAU2Xsc7oHd5HqWp2bts5AYauC1jCmYz JShdD3vI0/id1bysoCJI6hr59e8c/SPL38LWvWrhJyR+sWzbXn5bQpmdf3SJXg0E+jYO WHfQ== X-Gm-Message-State: AOJu0YyRB2/BHWEf10dBTnZWn2xlUBUT38KiZANq2op04S6NUNQh4E9x XzJU4r2vdEGicuzw5p6GGWzkw5//OxaSwOVXoZVLix2pPeWEybZr4NyWYCtemSJ5DE5lS8OrEr6 snn6kuhM4rzs8Rf9vJLS7g6ZacNaLihFP0tq25sALefLNwZG21Skm16eSrOFolWjMQabBXQKdWd IIuZoBfeYmTOa+S9V7b5gRJTf9SMWo/tO/YBnm X-Gm-Gg: ASbGncujPQSyQvcz/M0IItLM8Y+Co/kVyU3AFknvwgavQzzBn13P7aFlhmePIeiZnkL 1I7k1g8PmvtoNdPES78bTFLMJVv5ZYxubGPTT74z0OfJ08SUOokb7Xq5/dnnuTaz7psfE7RC5qH 16Tn+BEWOZwpqoETA/e+gAwq2aydNybd3LsfvoI8Sq6dwtM8JOTmdHEo8jw82dF+w3XMwhZuZnZ FthJpDPT2Yqusriv35mkdQJTkxctsrMFgpGRiG8EJh1+EQ2Z0e9Rw== X-Received: by 2002:a5d:5989:0:b0:385:de67:2269 with SMTP id ffacd0b85a97d-386453f67d0mr134689f8f.36.1733747869390; Mon, 09 Dec 2024 04:37:49 -0800 (PST) X-Google-Smtp-Source: AGHT+IH1jEk838B0P5aDCFXoIWlGcKXrjWlDpoOWk27luUi4kdcFBTVRh3sHrmTSDuTICl5fi5QAbA== X-Received: by 2002:a5d:5989:0:b0:385:de67:2269 with SMTP id ffacd0b85a97d-386453f67d0mr134658f8f.36.1733747868914; Mon, 09 Dec 2024 04:37:48 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 12/26] rust: qdev: move bridge for realize and reset functions out of pl011 Date: Mon, 9 Dec 2024 13:37:03 +0100 Message-ID: <20241209123717.99077-13-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=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: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733748855914116600 Content-Type: text/plain; charset="utf-8" Allow the DeviceImpl trait to expose safe Rust functions. rust_device_class_init<> adds thunks around the functions in DeviceImpl. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Zhao Liu <zhao1.liu@intel.com> --- rust/hw/char/pl011/src/device.rs | 5 ++-- rust/hw/char/pl011/src/device_class.rs | 26 ------------------- rust/qemu-api/src/definitions.rs | 2 +- rust/qemu-api/src/device_class.rs | 36 +++++++++++++++++++++----- 4 files changed, 33 insertions(+), 36 deletions(-) diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index 28b1924337d..56403c36609 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -125,9 +125,8 @@ fn properties() -> &'static [Property] { fn vmsd() -> Option<&'static VMStateDescription> { Some(&device_class::VMSTATE_PL011) } - const REALIZE: Option<unsafe extern "C" fn(*mut DeviceState, *mut *mut= Error)> =3D - Some(device_class::pl011_realize); - const RESET: Option<unsafe extern "C" fn(*mut DeviceState)> =3D Some(d= evice_class::pl011_reset); + const REALIZE: Option<fn(&mut Self)> =3D Some(Self::realize); + const RESET: Option<fn(&mut Self)> =3D Some(Self::reset); } =20 impl_device_class!(PL011State); diff --git a/rust/hw/char/pl011/src/device_class.rs b/rust/hw/char/pl011/sr= c/device_class.rs index c61b6bb0258..975c3d42be7 100644 --- a/rust/hw/char/pl011/src/device_class.rs +++ b/rust/hw/char/pl011/src/device_class.rs @@ -92,29 +92,3 @@ extern "C" fn pl011_post_load(opaque: *mut c_void, versi= on_id: c_int) -> c_int { default =3D true ), } - -/// # Safety -/// -/// We expect the FFI user of this function to pass a valid pointer, that = has -/// the same size as [`PL011State`]. We also expect the device is -/// readable/writeable from one thread at any time. -pub unsafe extern "C" fn pl011_realize(dev: *mut DeviceState, _errp: *mut = *mut Error) { - unsafe { - assert!(!dev.is_null()); - let mut state =3D NonNull::new_unchecked(dev.cast::<PL011State>()); - state.as_mut().realize(); - } -} - -/// # Safety -/// -/// We expect the FFI user of this function to pass a valid pointer, that = has -/// the same size as [`PL011State`]. We also expect the device is -/// readable/writeable from one thread at any time. -pub unsafe extern "C" fn pl011_reset(dev: *mut DeviceState) { - unsafe { - assert!(!dev.is_null()); - let mut state =3D NonNull::new_unchecked(dev.cast::<PL011State>()); - state.as_mut().reset(); - } -} diff --git a/rust/qemu-api/src/definitions.rs b/rust/qemu-api/src/definitio= ns.rs index 487712611f6..0467e6290e0 100644 --- a/rust/qemu-api/src/definitions.rs +++ b/rust/qemu-api/src/definitions.rs @@ -47,7 +47,7 @@ pub trait ObjectImpl: ClassInitImpl + Sized { /// Each QOM type has one such class struct. /// /// The Rust implementation of methods will usually come from a trait -/// like [`ObjectImpl`]. +/// like [`ObjectImpl`] or [`DeviceImpl`](crate::device_class::DeviceImpl). pub trait ClassInitImpl { /// Function that is called after all parent class initialization /// has occurred. On entry, the virtual method pointers are set to diff --git a/rust/qemu-api/src/device_class.rs b/rust/qemu-api/src/device_c= lass.rs index f683f94f2a5..f25904be4f6 100644 --- a/rust/qemu-api/src/device_class.rs +++ b/rust/qemu-api/src/device_class.rs @@ -17,14 +17,14 @@ pub trait DeviceImpl { /// /// If not `None`, the parent class's `realize` method is overridden /// with the function pointed to by `REALIZE`. - const REALIZE: Option<unsafe extern "C" fn(*mut DeviceState, *mut *mut= Error)> =3D None; + const REALIZE: Option<fn(&mut Self)> =3D None; =20 /// If not `None`, the parent class's `reset` method is overridden /// with the function pointed to by `RESET`. /// /// Rust does not yet support the three-phase reset protocol; this is /// usually okay for leaf classes. - const RESET: Option<unsafe extern "C" fn(dev: *mut DeviceState)> =3D N= one; + const RESET: Option<fn(&mut Self)> =3D None; =20 /// An array providing the properties that the user can set on the /// device. Not a `const` because referencing statics in constants @@ -41,6 +41,30 @@ fn vmsd() -> Option<&'static VMStateDescription> { } } =20 +/// # Safety +/// +/// This function is only called through the QOM machinery and +/// the `impl_device_class!` macro. +/// We expect the FFI user of this function to pass a valid pointer that +/// can be downcasted to type `T`. We also expect the device is +/// readable/writeable from one thread at any time. +unsafe extern "C" fn rust_realize_fn<T: DeviceImpl>(dev: *mut DeviceState,= _errp: *mut *mut Error) { + assert!(!dev.is_null()); + let state =3D dev.cast::<T>(); + T::REALIZE.unwrap()(unsafe { &mut *state }); +} + +/// # Safety +/// +/// We expect the FFI user of this function to pass a valid pointer that +/// can be downcasted to type `T`. We also expect the device is +/// readable/writeable from one thread at any time. +unsafe extern "C" fn rust_reset_fn<T: DeviceImpl>(dev: *mut DeviceState) { + assert!(!dev.is_null()); + let state =3D dev.cast::<T>(); + T::RESET.unwrap()(unsafe { &mut *state }); +} + /// # Safety /// /// We expect the FFI user of this function to pass a valid pointer that @@ -53,11 +77,11 @@ fn vmsd() -> Option<&'static VMStateDescription> { let mut dc =3D ::core::ptr::NonNull::new(klass.cast::<DeviceClass>()).= unwrap(); unsafe { let dc =3D dc.as_mut(); - if let Some(realize_fn) =3D <T as DeviceImpl>::REALIZE { - dc.realize =3D Some(realize_fn); + if <T as DeviceImpl>::REALIZE.is_some() { + dc.realize =3D Some(rust_realize_fn::<T>); } - if let Some(reset_fn) =3D <T as DeviceImpl>::RESET { - bindings::device_class_set_legacy_reset(dc, Some(reset_fn)); + if <T as DeviceImpl>::RESET.is_some() { + bindings::device_class_set_legacy_reset(dc, Some(rust_reset_fn= ::<T>)); } if let Some(vmsd) =3D <T as DeviceImpl>::vmsd() { dc.vmsd =3D vmsd; --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733748113; cv=none; d=zohomail.com; s=zohoarc; b=OPaWXHJVHJu561yTDsglLOFRXpPk95CvfxQwtgH6sJu9gnHarjTJ+AWRuyxUOJdzK0KrGWxgqfrj8Xlns3/fG4dnhVPcmBolf6VVJobPIKhflwDAOa//w1yXmHRsx2BLpHrTh2IpOV+an19XLA+GucgRFEnpZ+BvqF6GMV8tG7Y= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733748113; 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=yc6FheuyZyH/oA7b36KKccLApc1+iqI4hAPCi9UKt0s=; b=KGyn5fo8Edp1460IIHEpcEQChce/umjZJEnnpePXLIYCW8tRb5Mmi1nouq5tgA32P5ErfOHqyBQ3CZfg5dmSFtr2u+d3aT6pNfUQVgdwtOAmyHE0rLKlt+NYRd50le1IDzj+gY1Rcmrwc4sxYOp0RE5sU8zFTRQYH+NdqXw7F7g= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733748113549329.1594237354615; Mon, 9 Dec 2024 04:41:53 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd2n-000503-R1; Mon, 09 Dec 2024 07:39:26 -0500 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 <pbonzini@redhat.com>) id 1tKd1S-0003z2-Rx for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:59 -0500 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 <pbonzini@redhat.com>) id 1tKd1P-0007TK-OL for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:37:58 -0500 Received: from mail-wm1-f70.google.com (mail-wm1-f70.google.com [209.85.128.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-166-OIl3S_9hO3CESclEld4GHQ-1; Mon, 09 Dec 2024 07:37:54 -0500 Received: by mail-wm1-f70.google.com with SMTP id 5b1f17b1804b1-434e81cad70so16184315e9.2 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:37:53 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-434f43aedb2sm55069405e9.41.2024.12.09.04.37.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:37:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747875; 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=yc6FheuyZyH/oA7b36KKccLApc1+iqI4hAPCi9UKt0s=; b=BXJMp1qJL1V2a9J0R9Rt/RZkDnJbvId0cbazSwHtI7GCCTDReiyssbEFj8W9Dlbh4KFWIy DpLTe+iJwibzV7XPO8kMz5vwN+9INyXY/uFmG1jxtFucDgmTmJeVfilLgmlq9G7LuMzjU+ KXs9p3vZuePLPmwJIVY1qgmD1f6dZpM= X-MC-Unique: OIl3S_9hO3CESclEld4GHQ-1 X-Mimecast-MFC-AGG-ID: OIl3S_9hO3CESclEld4GHQ X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747872; x=1734352672; 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=yc6FheuyZyH/oA7b36KKccLApc1+iqI4hAPCi9UKt0s=; b=IwGZU191Rd1ayzhsghZGdqRGUKjo8LRgOnfbtuVZ9Vk5z0djG9smnvbqaI/cLWxuPF sz39b+GGd0tOsxHxkd6oNY2CddPGfMp0l6oUCB4SWoOaU1RjoqhakXbopwGAapOqgeIE /Vtf78zGG82492VN3ywX2QQnlV58/+w76jMHrH+9Tf7TS3l3HZ1DcCXW0zgHCMBgr3NG Wj9aBiZv5Jg0xjMBTqPhsSZG0eoYxvfRMTe631JPKi/N8t9M6E4Qi6svPZLp7Xd7fOgT 2EZo8cnYbrBiupiQZVNxNOP/cx4JehjPV4rW9e8IOtIhGOmpicVvpAH8keoyWnksZA4z Owfw== X-Gm-Message-State: AOJu0YzzCvps8PZxoJJ+/YgqBM4/e2QnQkPw3KWk+vae69fHmxBo1aO1 tu51G6c4hnYevTVwM050WkCZzCX0KGn/xhZOv171r2Z/neLRXvjj7brVy4aLnodWZleG+js4mz+ cCMy8oghl8lF/eyjFA4mCa/q9xExQ6S3zfdlBWSuNByn0F60S8AEkV6W03t6ZHk8C2xfhM2GWgY AIcW2u8PJRmDvDKp3PxHbCoXDZV2lrwEGWadQk X-Gm-Gg: ASbGncv3U5rbxS1uDWg4NAg9ZtqnDjTC6ZtKCfNKTNvBbKYuXgypjIYIIJqZ+wvb6fL NIFIhAxCAo1I+0yU/AINCvJ0liBXJk4ca0d/aXH7rSwQ7ylUJzW8TNPkRJKcMly4sal5CEJgksQ ImGYYt/zoDTlDnw9NNIYYmaBtRjFGYs8nyY3EzP3AAaGxW3d2zfkzXE8okAXWKlPf7TOGr/egih AORFqeEnZHPgsSJVlIdRYHj8B1GzJq/3/7MmetDSnqErKpxKn52Cw== X-Received: by 2002:a05:600c:458c:b0:434:9ec0:9e4e with SMTP id 5b1f17b1804b1-434fffba059mr3550135e9.30.1733747871697; Mon, 09 Dec 2024 04:37:51 -0800 (PST) X-Google-Smtp-Source: AGHT+IEXo5oYAIaHVB3/q0A3uBCASjycc1vAb0yhaygilhId7tYKgqlabvux4EtEuo9ZUx2wrcbr3A== X-Received: by 2002:a05:600c:458c:b0:434:9ec0:9e4e with SMTP id 5b1f17b1804b1-434fffba059mr3549755e9.30.1733747871210; Mon, 09 Dec 2024 04:37:51 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 13/26] rust: qom: automatically use Drop trait to implement instance_finalize Date: Mon, 9 Dec 2024 13:37:04 +0100 Message-ID: <20241209123717.99077-14-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=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: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733748114939116600 Content-Type: text/plain; charset="utf-8" Replace the customizable INSTANCE_FINALIZE with a generic function that drops the Rust object. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Zhao Liu <zhao1.liu@intel.com> --- rust/qemu-api/src/definitions.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/rust/qemu-api/src/definitions.rs b/rust/qemu-api/src/definitio= ns.rs index 0467e6290e0..d64a581a5cc 100644 --- a/rust/qemu-api/src/definitions.rs +++ b/rust/qemu-api/src/definitions.rs @@ -8,6 +8,13 @@ =20 use crate::bindings::{Object, ObjectClass, TypeInfo}; =20 +unsafe extern "C" fn drop_object<T: ObjectImpl>(obj: *mut Object) { + // SAFETY: obj is an instance of T, since drop_object<T> + // is called from QOM core as the instance_finalize function + // for class T + unsafe { std::ptr::drop_in_place(obj.cast::<T>()) } +} + /// Trait a type must implement to be registered with QEMU. pub trait ObjectImpl: ClassInitImpl + Sized { type Class; @@ -16,7 +23,6 @@ pub trait ObjectImpl: ClassInitImpl + Sized { const ABSTRACT: bool =3D false; const INSTANCE_INIT: Option<unsafe extern "C" fn(obj: *mut Object)> = =3D None; const INSTANCE_POST_INIT: Option<unsafe extern "C" fn(obj: *mut Object= )> =3D None; - const INSTANCE_FINALIZE: Option<unsafe extern "C" fn(obj: *mut Object)= > =3D None; =20 const TYPE_INFO: TypeInfo =3D TypeInfo { name: Self::TYPE_NAME.as_ptr(), @@ -29,7 +35,7 @@ pub trait ObjectImpl: ClassInitImpl + Sized { instance_align: core::mem::align_of::<Self>(), instance_init: Self::INSTANCE_INIT, instance_post_init: Self::INSTANCE_POST_INIT, - instance_finalize: Self::INSTANCE_FINALIZE, + instance_finalize: Some(drop_object::<Self>), abstract_: Self::ABSTRACT, class_size: core::mem::size_of::<Self::Class>(), class_init: <Self as ClassInitImpl>::CLASS_INIT, --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733748564; cv=none; d=zohomail.com; s=zohoarc; b=AioILEmnmpUJDURAX8R8aQuqmOXcTM28oYPC+8STEZHlqvJiHOIuzXUulQqDIdcFtMkZwy8huSZ6GsQPypBhXIiZnOro2f78kXrrEu3hVzfn1L41c6IKirX3dKktwZR/uxiKHWAQ/7106xa8+eN33BwU5mVYIl9AFKs/GXBB48k= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733748564; 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=lTYy1Da2MVUyx5e12TuwendQ6h8bg1WbLVoDyiNBJFQ=; b=Wq5xqLU32JKoJKtpGMWDiLZ7ruVTLgAg5MaBPII/ol52Pc0QJgjJoUdmi5nfcnAkQCh4ItoAilSKmEfM6+AzH89bpU6fe6FGRV9VJxceAAanqhy00PAsLTx5Uk/ulxsFDrm2JJuvqJoPektBA/31sC5S7V3z/TuwlJWQJ/kl4rc= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733748564582390.92002309602333; Mon, 9 Dec 2024 04:49:24 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd3G-0005sJ-7X; Mon, 09 Dec 2024 07:39:57 -0500 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 <pbonzini@redhat.com>) id 1tKd1Y-00041y-17 for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:04 -0500 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 <pbonzini@redhat.com>) id 1tKd1T-0007UD-Oi for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:03 -0500 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-173-yJySlSPtMR66Y_TnshMa5Q-1; Mon, 09 Dec 2024 07:37:56 -0500 Received: by mail-wm1-f69.google.com with SMTP id 5b1f17b1804b1-434f112d83aso13047535e9.3 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:37:56 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-434fe9bff74sm8411475e9.8.2024.12.09.04.37.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:37:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747878; 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=lTYy1Da2MVUyx5e12TuwendQ6h8bg1WbLVoDyiNBJFQ=; b=V9Q1YD3g6rwHH1FWMl/KxKxaU4FGzSMKSWBewK/147Ld0Y2nOavgHs9uGZKwStxmPbZRuu 6jigdSJ1RSerJQ8qxaeJ0vEkwGx6uHki7735oMWy7004njrv9OMzCf6k+Zc2q9I1THgMqh 6TDdiLqpk/dEykoKZi1dy+UPoFi8G0A= X-MC-Unique: yJySlSPtMR66Y_TnshMa5Q-1 X-Mimecast-MFC-AGG-ID: yJySlSPtMR66Y_TnshMa5Q X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747875; x=1734352675; 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=lTYy1Da2MVUyx5e12TuwendQ6h8bg1WbLVoDyiNBJFQ=; b=PaFhE21ASMLUrG5rnuI/Q9X/SlcEofpBWPERjj4rf4k+XkYCSmnE21T43hBiY/ADkD +eN2IQy4hdxD1qzpl8unr9YKzEyfu6a5MsKRl0BwQsvtEl0M2vxlG5RVbdbsnSfbXkDB GC8E7hjy46eX0ZLqCxSK2KYWR7TDhK5plZQVEj1sZMqkQx8ADl72PqjO69i6OW0mnCs7 rIN5VvYzyUi7Q0i1WHNJyUp7GnjWTX2WKotb7BqgUrBNPe/SqGf5WAi0HA/rKM8qpLMC KnaoEYaDXqHOpN7Ld0GaO57RQ3Lz/Q4xkwCHWk0pTME3GYq1k1DJEtDQtfOFdwpsb8j7 q49g== X-Gm-Message-State: AOJu0Yy3tslaumC7HcdRpLerP4Ot5QPswzxq2yJWj0HC/T4XqX8uFw19 kz4UDjl59M93psAcHFde9Pms75zQzQQgCRt/DHzX1HPI7bjKY/g9s7L3nxWnjFV2gjodJJ2qAmU QBwSvYztkV6itubJHE6GbL9sjEsW8gOiioFjcOARuQdq+goqF40IQ3RYZWMhHuNQOlrF/I3P6PQ vqHeRLwjK/pJmL69PRQ5C2xX+INU3abVZQVC7R X-Gm-Gg: ASbGnctr8X82/l2geUt7bJsMrxYG1UJxBwkToRiQs5dRwo6aXzB4VSnQR2byVWWN4jW YBtOeKKqOCXOIbCIWXvD38eN+f28IHcPfaS60nszq6zDvwQE36jEx+gTIlLhlTI60SaRt+eXZoI LAevbx+Hh/haoN6b5OIv/KIrNqWOOj1fdYGJuHhflp/0HBROyY1aMLfvk1FM2+BSHcc/DyHJgAi PrgFDB7H6rTGZiqk9rv/EFYiTWZtL5hmE/mTS3+pHq2V0WWo+R21Q== X-Received: by 2002:a05:600c:34c4:b0:434:feb1:adbb with SMTP id 5b1f17b1804b1-434feb1b243mr10131935e9.31.1733747874617; Mon, 09 Dec 2024 04:37:54 -0800 (PST) X-Google-Smtp-Source: AGHT+IFwu/ZgjtodbmY64bjy8c55kmq1254rX8DfOYm502NBkpVP7V98xEWbRE5TfNt/ZYFiMhTvCA== X-Received: by 2002:a05:600c:34c4:b0:434:feb1:adbb with SMTP id 5b1f17b1804b1-434feb1b243mr10131655e9.31.1733747874157; Mon, 09 Dec 2024 04:37:54 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 14/26] rust: qom: move bridge for TypeInfo functions out of pl011 Date: Mon, 9 Dec 2024 13:37:05 +0100 Message-ID: <20241209123717.99077-15-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, 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_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=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: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733748566924116600 Content-Type: text/plain; charset="utf-8" Allow the ObjectImpl trait to expose Rust functions that avoid raw pointers (though INSTANCE_INIT for example is still unsafe). ObjectImpl::TYPE_INFO adds thunks around the functions in ObjectImpl. While at it, document `TypeInfo`. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Zhao Liu <zhao1.liu@intel.com> --- rust/hw/char/pl011/src/device.rs | 40 +++++++-------------- rust/qemu-api/src/definitions.rs | 61 +++++++++++++++++++++++++++++--- 2 files changed, 69 insertions(+), 32 deletions(-) diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index 56403c36609..b9f8fb134b5 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -110,7 +110,7 @@ impl ObjectImpl for PL011State { type Class =3D PL011Class; const TYPE_NAME: &'static CStr =3D crate::TYPE_PL011; const PARENT_TYPE_NAME: Option<&'static CStr> =3D Some(TYPE_SYS_BUS_DE= VICE); - const INSTANCE_INIT: Option<unsafe extern "C" fn(obj: *mut Object)> = =3D Some(pl011_init); + const INSTANCE_INIT: Option<unsafe fn(&mut Self)> =3D Some(Self::init); } =20 #[repr(C)] @@ -615,19 +615,6 @@ pub fn post_load(&mut self, _version_id: u32) -> Resul= t<(), ()> { } } =20 -/// # Safety -/// -/// We expect the FFI user of this function to pass a valid pointer, that = has -/// the same size as [`PL011State`]. We also expect the device is -/// readable/writeable from one thread at any time. -pub unsafe extern "C" fn pl011_init(obj: *mut Object) { - unsafe { - debug_assert!(!obj.is_null()); - let mut state =3D NonNull::new_unchecked(obj.cast::<PL011State>()); - state.as_mut().init(); - } -} - #[repr(C)] #[derive(Debug, qemu_api_macros::Object)] /// PL011 Luminary device model. @@ -640,19 +627,16 @@ pub struct PL011LuminaryClass { _inner: [u8; 0], } =20 -/// Initializes a pre-allocated, unitialized instance of `PL011Luminary`. -/// -/// # Safety -/// -/// We expect the FFI user of this function to pass a valid pointer, that = has -/// the same size as [`PL011Luminary`]. We also expect the device is -/// readable/writeable from one thread at any time. -pub unsafe extern "C" fn pl011_luminary_init(obj: *mut Object) { - unsafe { - debug_assert!(!obj.is_null()); - let mut state =3D NonNull::new_unchecked(obj.cast::<PL011Luminary>= ()); - let state =3D state.as_mut(); - state.parent_obj.device_id =3D DeviceId::Luminary; +impl PL011Luminary { + /// Initializes a pre-allocated, unitialized instance of `PL011Luminar= y`. + /// + /// # Safety + /// + /// We expect the FFI user of this function to pass a valid pointer, t= hat + /// has the same size as [`PL011Luminary`]. We also expect the device = is + /// readable/writeable from one thread at any time. + unsafe fn init(&mut self) { + self.parent_obj.device_id =3D DeviceId::Luminary; } } =20 @@ -660,7 +644,7 @@ impl ObjectImpl for PL011Luminary { type Class =3D PL011LuminaryClass; const TYPE_NAME: &'static CStr =3D crate::TYPE_PL011_LUMINARY; const PARENT_TYPE_NAME: Option<&'static CStr> =3D Some(crate::TYPE_PL0= 11); - const INSTANCE_INIT: Option<unsafe extern "C" fn(obj: *mut Object)> = =3D Some(pl011_luminary_init); + const INSTANCE_INIT: Option<unsafe fn(&mut Self)> =3D Some(Self::init); } =20 impl DeviceImpl for PL011Luminary {} diff --git a/rust/qemu-api/src/definitions.rs b/rust/qemu-api/src/definitio= ns.rs index d64a581a5cc..078ba30d61a 100644 --- a/rust/qemu-api/src/definitions.rs +++ b/rust/qemu-api/src/definitions.rs @@ -8,6 +8,24 @@ =20 use crate::bindings::{Object, ObjectClass, TypeInfo}; =20 +unsafe extern "C" fn rust_instance_init<T: ObjectImpl>(obj: *mut Object) { + // SAFETY: obj is an instance of T, since rust_instance_init<T> + // is called from QOM core as the instance_init function + // for class T + unsafe { T::INSTANCE_INIT.unwrap()(&mut *obj.cast::<T>()) } +} + +unsafe extern "C" fn rust_instance_post_init<T: ObjectImpl>(obj: *mut Obje= ct) { + // SAFETY: obj is an instance of T, since rust_instance_post_init<T> + // is called from QOM core as the instance_post_init function + // for class T + // + // FIXME: it's not really guaranteed that there are no backpointers to + // obj; it's quite possible that they have been created by instance_in= it(). + // The receiver should be &self, not &mut self. + T::INSTANCE_POST_INIT.unwrap()(unsafe { &mut *obj.cast::<T>() }) +} + unsafe extern "C" fn drop_object<T: ObjectImpl>(obj: *mut Object) { // SAFETY: obj is an instance of T, since drop_object<T> // is called from QOM core as the instance_finalize function @@ -16,13 +34,42 @@ } =20 /// Trait a type must implement to be registered with QEMU. +/// +/// # Safety +/// +/// - the struct must be `#[repr(C)]` +/// +/// - `Class` and `TYPE` must match the data in the `TypeInfo` (this is +/// automatic if the class is defined via `ObjectImpl`). +/// +/// - the first field of the struct must be of the instance struct corresp= onding +/// to the superclass declared as `PARENT_TYPE_NAME` pub trait ObjectImpl: ClassInitImpl + Sized { + /// The QOM class object corresponding to this struct. Not used yet. type Class; + + /// The name of the type, which can be passed to `object_new()` to + /// generate an instance of this type. const TYPE_NAME: &'static CStr; + + /// The parent of the type. This should match the first field of + /// the struct that implements `ObjectImpl`: const PARENT_TYPE_NAME: Option<&'static CStr>; + + /// Whether the object can be instantiated const ABSTRACT: bool =3D false; - const INSTANCE_INIT: Option<unsafe extern "C" fn(obj: *mut Object)> = =3D None; - const INSTANCE_POST_INIT: Option<unsafe extern "C" fn(obj: *mut Object= )> =3D None; + + /// Function that is called to initialize an object. The parent class= will + /// have already been initialized so the type is only responsible for + /// initializing its own members. + /// + /// FIXME: The argument is not really a valid reference. `&mut + /// MaybeUninit<Self>` would be a better description. + const INSTANCE_INIT: Option<unsafe fn(&mut Self)> =3D None; + + /// Function that is called to finish initialization of an object, once + /// `INSTANCE_INIT` functions have been called. + const INSTANCE_POST_INIT: Option<fn(&mut Self)> =3D None; =20 const TYPE_INFO: TypeInfo =3D TypeInfo { name: Self::TYPE_NAME.as_ptr(), @@ -33,8 +80,14 @@ pub trait ObjectImpl: ClassInitImpl + Sized { }, instance_size: core::mem::size_of::<Self>(), instance_align: core::mem::align_of::<Self>(), - instance_init: Self::INSTANCE_INIT, - instance_post_init: Self::INSTANCE_POST_INIT, + instance_init: match Self::INSTANCE_INIT { + None =3D> None, + Some(_) =3D> Some(rust_instance_init::<Self>), + }, + instance_post_init: match Self::INSTANCE_POST_INIT { + None =3D> None, + Some(_) =3D> Some(rust_instance_post_init::<Self>), + }, instance_finalize: Some(drop_object::<Self>), abstract_: Self::ABSTRACT, class_size: core::mem::size_of::<Self::Class>(), --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733748525; cv=none; d=zohomail.com; s=zohoarc; b=bBNThQgM25yHinUNhXyJ3MP/WYWUw8NKibGfJoLnST04Z9QxE7ipjLv7t7+JCq4Mmq10TPqz4XVT1wkE/6A7x9FoZYa+W56rhjfhp/HuKJYO3eD+2hAmRHpU2RIu66m+DNBbfQRvWJjtym5qi7gqrZmMmb5gs03YMW+7VIXJCRY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733748525; 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=mN7zrOvP9fPOWB30Q4ZH63TTQ13EdvwykjuYF0Tturg=; b=Z4ss7MEkb5zRCHexIYlhZrUcRWksTxE2auze8EMtrU/IcX5pb6ChXQRl5nFCvqVYPD4xn3VymCaJAejqhHFgPFoWF/nRaHMMUc0625klEJz4Ajbckz8HmgeA0N0jkloBMsWiyIeL3oRVjeHmB+BOoSjz5YP1VvuyOxILzemmkhc= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733748525394386.9321443144977; Mon, 9 Dec 2024 04:48:45 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd4G-0006fv-Nb; Mon, 09 Dec 2024 07:40:52 -0500 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 <pbonzini@redhat.com>) id 1tKd1W-00041S-Ey for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:03 -0500 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 <pbonzini@redhat.com>) id 1tKd1U-0007UR-7Y for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:02 -0500 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-160-BqU_4apUPwO1vQZp7b9ilw-1; Mon, 09 Dec 2024 07:37:58 -0500 Received: by mail-wr1-f71.google.com with SMTP id ffacd0b85a97d-386333ea577so759525f8f.1 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:37:58 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-386219095desm12945066f8f.64.2024.12.09.04.37.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:37:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747879; 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=mN7zrOvP9fPOWB30Q4ZH63TTQ13EdvwykjuYF0Tturg=; b=aEUNvG80RAxW8xY1i6IY0CXYmIbckSIxxZF3LaDTJ6VUppoXm0OOAycsJ3WxmjCCm/Uo1p Y2tLZz6MlbsLXRc83uJYi2s+S9FzsWdneX+LlS8HFnX2G2lUdKDZSC5Ll+v8QHj82jkGKB hiFpgFA0ntZPlEmFYRxeCIzmFVo+ucs= X-MC-Unique: BqU_4apUPwO1vQZp7b9ilw-1 X-Mimecast-MFC-AGG-ID: BqU_4apUPwO1vQZp7b9ilw X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747877; x=1734352677; 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=mN7zrOvP9fPOWB30Q4ZH63TTQ13EdvwykjuYF0Tturg=; b=QzaQQHaEJK9nks4aYEH6bBlvtJuPlHMQcB+f1vEKPzsMO57PdSq1opSS2HU6Cv2GBI ZTwvEy5BvcC/WpAQXMKnlgOE/l/exPTdgKxyMFjPRJE7u3sJTczBZg9n4AZmpU5+/E+n sgLIrQ6C8D1j9wFh45kjmFQHkdSrKHUhGjx1atCh0O5I7UTThSvuz4t00q7sBbrLwSoy N9kieeQEUr9Tw/91IdpfNyVQOcqTKDb0fEeGAxPjZbmE+rQDicBJKCEPdfisE6c+8bVc rw8i/vlmInuF/wkSm8FsRxwQjr9ZQi5c2i/hX2NFZuLWPv/wTuuqHQtl7X2gkSQuHr41 MZSQ== X-Gm-Message-State: AOJu0YxIa0CaeE1X67I+zN4qwLV6EHLgGbvF8jpwqy0r4ZfO4OV3qGFF WsaBCW1J+Gbi0nxlp/FWBAphLJc/FeUD3kmz+g2/ADah/2rsAcv1+IYex8UuzsKJAL1vriWkmYM iIATcCNzWn40OVMNKHxf8ftnSjF6eV7948AH1sNZeyb7zT+rbBR7g3GgyNOMW7MwNbW43+g2dSc LcQqjkNLff02RXYdPGlXJj8+XsSNvlCvzIjMTA X-Gm-Gg: ASbGncvZQryfCh8fFRO5hg2YG7ZAk2LpddMxka3tfI6qxgerTEadOR1YtejYkM2xtPo mrQizvlPjQ3M82L1S/Hqj+Uw3e+bJMTy+juV63AXebRWCI5v5yQKiqtVsF3EhwfWu6W3bEQU+TG 9HW/s4ljSLGUH+ECLkIuaZ9Qy+pTUMVJGOwTIukNNLjgwQCgyTFSXSiWKr1s9mdjKR/hnP0DUBh W5D80H+Ia+N/5easxz28A1j+0IAX+EYuhjbqQ4pb306wfD8wpA9ZQ== X-Received: by 2002:a05:6000:178e:b0:385:df73:2f3a with SMTP id ffacd0b85a97d-386453d4a54mr160174f8f.14.1733747876731; Mon, 09 Dec 2024 04:37:56 -0800 (PST) X-Google-Smtp-Source: AGHT+IFK/bmRmdfEMxIc0cApSfDYi7hd5M035oIFTVRxbtpUO8gW1R+kgunjwoZRfGCg4ObKF9jehA== X-Received: by 2002:a05:6000:178e:b0:385:df73:2f3a with SMTP id ffacd0b85a97d-386453d4a54mr160147f8f.14.1733747876315; Mon, 09 Dec 2024 04:37:56 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 15/26] rust: qom: split ObjectType from ObjectImpl trait Date: Mon, 9 Dec 2024 13:37:06 +0100 Message-ID: <20241209123717.99077-16-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=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: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733748526736116600 Content-Type: text/plain; charset="utf-8" Define a separate trait for fields that also applies to classes that are defined by C code. This makes it possible to add metadata to core classes, which has multiple uses: - it makes it possible to access the parent struct's TYPE_* for types that are defined in Rust code, and to avoid repeating it in every subclass - implementors of ObjectType will be allowed to implement the IsA<> trait a= nd therefore to perform typesafe casts from one class to another. - in the future, an ObjectType could be created with Foo::new() in a type-s= afe manner, without having to pass a TYPE_* constant. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Zhao Liu <zhao1.liu@intel.com> --- rust/hw/char/pl011/src/device.rs | 17 ++++++++++++----- rust/qemu-api/src/definitions.rs | 9 ++++++--- rust/qemu-api/src/device_class.rs | 11 ++++++----- rust/qemu-api/src/prelude.rs | 2 ++ rust/qemu-api/src/sysbus.rs | 10 ++++++++-- rust/qemu-api/tests/tests.rs | 12 +++++++++--- 6 files changed, 43 insertions(+), 18 deletions(-) diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index b9f8fb134b5..0ab825b1ca4 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -12,9 +12,10 @@ bindings::{self, *}, c_str, definitions::ObjectImpl, - device_class::{DeviceImpl, TYPE_SYS_BUS_DEVICE}, + device_class::DeviceImpl, impl_device_class, irq::InterruptSource, + prelude::*, }; =20 use crate::{ @@ -106,10 +107,13 @@ pub struct PL011State { device_id: DeviceId, } =20 -impl ObjectImpl for PL011State { +unsafe impl ObjectType for PL011State { type Class =3D PL011Class; const TYPE_NAME: &'static CStr =3D crate::TYPE_PL011; - const PARENT_TYPE_NAME: Option<&'static CStr> =3D Some(TYPE_SYS_BUS_DE= VICE); +} + +impl ObjectImpl for PL011State { + const PARENT_TYPE_NAME: Option<&'static CStr> =3D Some(<SysBusDevice a= s ObjectType>::TYPE_NAME); const INSTANCE_INIT: Option<unsafe fn(&mut Self)> =3D Some(Self::init); } =20 @@ -640,10 +644,13 @@ unsafe fn init(&mut self) { } } =20 -impl ObjectImpl for PL011Luminary { +unsafe impl ObjectType for PL011Luminary { type Class =3D PL011LuminaryClass; const TYPE_NAME: &'static CStr =3D crate::TYPE_PL011_LUMINARY; - const PARENT_TYPE_NAME: Option<&'static CStr> =3D Some(crate::TYPE_PL0= 11); +} + +impl ObjectImpl for PL011Luminary { + const PARENT_TYPE_NAME: Option<&'static CStr> =3D Some(<PL011State as = ObjectType>::TYPE_NAME); const INSTANCE_INIT: Option<unsafe fn(&mut Self)> =3D Some(Self::init); } =20 diff --git a/rust/qemu-api/src/definitions.rs b/rust/qemu-api/src/definitio= ns.rs index 078ba30d61a..1c412dbc876 100644 --- a/rust/qemu-api/src/definitions.rs +++ b/rust/qemu-api/src/definitions.rs @@ -33,7 +33,7 @@ unsafe { std::ptr::drop_in_place(obj.cast::<T>()) } } =20 -/// Trait a type must implement to be registered with QEMU. +/// Trait exposed by all structs corresponding to QOM objects. /// /// # Safety /// @@ -43,15 +43,18 @@ /// automatic if the class is defined via `ObjectImpl`). /// /// - the first field of the struct must be of the instance struct corresp= onding -/// to the superclass declared as `PARENT_TYPE_NAME` -pub trait ObjectImpl: ClassInitImpl + Sized { +/// to the superclass declared in the `TypeInfo` +pub unsafe trait ObjectType: Sized { /// The QOM class object corresponding to this struct. Not used yet. type Class; =20 /// The name of the type, which can be passed to `object_new()` to /// generate an instance of this type. const TYPE_NAME: &'static CStr; +} =20 +/// Trait a type must implement to be registered with QEMU. +pub trait ObjectImpl: ObjectType + ClassInitImpl { /// The parent of the type. This should match the first field of /// the struct that implements `ObjectImpl`: const PARENT_TYPE_NAME: Option<&'static CStr>; diff --git a/rust/qemu-api/src/device_class.rs b/rust/qemu-api/src/device_c= lass.rs index f25904be4f6..03d03feee83 100644 --- a/rust/qemu-api/src/device_class.rs +++ b/rust/qemu-api/src/device_class.rs @@ -6,6 +6,7 @@ =20 use crate::{ bindings::{self, DeviceClass, DeviceState, Error, ObjectClass, Propert= y, VMStateDescription}, + prelude::*, zeroable::Zeroable, }; =20 @@ -146,8 +147,8 @@ macro_rules! declare_properties { }; } =20 -// workaround until we can use --generate-cstr in bindgen. -pub const TYPE_DEVICE: &CStr =3D - unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_DEVICE) }; -pub const TYPE_SYS_BUS_DEVICE: &CStr =3D - unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_SYS_BUS_DE= VICE) }; +unsafe impl ObjectType for bindings::DeviceState { + type Class =3D bindings::DeviceClass; + const TYPE_NAME: &'static CStr =3D + unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_DEVICE= ) }; +} diff --git a/rust/qemu-api/src/prelude.rs b/rust/qemu-api/src/prelude.rs index a39e228babf..1b8677b2d9a 100644 --- a/rust/qemu-api/src/prelude.rs +++ b/rust/qemu-api/src/prelude.rs @@ -6,3 +6,5 @@ =20 pub use crate::cell::BqlCell; pub use crate::cell::BqlRefCell; + +pub use crate::definitions::ObjectType; diff --git a/rust/qemu-api/src/sysbus.rs b/rust/qemu-api/src/sysbus.rs index 4e192c75898..5ee068541cf 100644 --- a/rust/qemu-api/src/sysbus.rs +++ b/rust/qemu-api/src/sysbus.rs @@ -2,11 +2,17 @@ // Author(s): Paolo Bonzini <pbonzini@redhat.com> // SPDX-License-Identifier: GPL-2.0-or-later =20 -use std::ptr::addr_of; +use std::{ffi::CStr, ptr::addr_of}; =20 pub use bindings::{SysBusDevice, SysBusDeviceClass}; =20 -use crate::{bindings, cell::bql_locked, irq::InterruptSource}; +use crate::{bindings, cell::bql_locked, irq::InterruptSource, prelude::*}; + +unsafe impl ObjectType for SysBusDevice { + type Class =3D SysBusDeviceClass; + const TYPE_NAME: &'static CStr =3D + unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_SYS_BU= S_DEVICE) }; +} =20 impl SysBusDevice { /// Return `self` cast to a mutable pointer, for use in calls to C cod= e. diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index b8b12a40422..1be03eb685c 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -8,8 +8,9 @@ bindings::*, c_str, declare_properties, define_property, definitions::ObjectImpl, - device_class::{self, DeviceImpl}, + device_class::DeviceImpl, impl_device_class, + prelude::*, zeroable::Zeroable, }; =20 @@ -46,10 +47,15 @@ pub struct DummyClass { ), } =20 - impl ObjectImpl for DummyState { + unsafe impl ObjectType for DummyState { type Class =3D DummyClass; const TYPE_NAME: &'static CStr =3D c_str!("dummy"); - const PARENT_TYPE_NAME: Option<&'static CStr> =3D Some(device_clas= s::TYPE_DEVICE); + } + + impl ObjectImpl for DummyState { + const PARENT_TYPE_NAME: Option<&'static CStr> =3D + Some(<DeviceState as ObjectType>::TYPE_NAME); + const ABSTRACT: bool =3D false; } =20 impl DeviceImpl for DummyState { --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733748429; cv=none; d=zohomail.com; s=zohoarc; b=LL2QzGEcm0DgWOkpOAnYYWtGme3U7XO6JWYYE2BjdIRjgR+K+u9oSiY/uI9XDhOYu2A5ivKHVQA2/UFz8ZrIneynZ5qYunTcBxZ1yN9nQBZahdYFg9PLuTPyLWk+cP/vVyGSRRl/pB/vA378UqURjQUnBsA8jtK0KsIk9+SKZ/c= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733748429; 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=aQQh40wwBPdVycCz9xzGGWLkoYV4qfuAlbHWnwDiqjM=; b=hli6yUDqrCBlV97NASA1wuJAxdJp7Gce/Q+rgLhhxLtQMIALLxMb4ZG7nRp8jsDA3bSdGTrBNLlXeqy+knHMT/bvmBJmLkpHFlWkdiC0O51JNeXkWvkZX+EXRxcoMz7OsPnc56GcCHRUuggl9D5tIUe4CfoGpEF34hgXfJ1qoV8= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733748429620841.4027348657875; Mon, 9 Dec 2024 04:47:09 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd2W-0004g5-V6; Mon, 09 Dec 2024 07:39:07 -0500 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 <pbonzini@redhat.com>) id 1tKd1Z-000422-JF for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:06 -0500 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 <pbonzini@redhat.com>) id 1tKd1W-0007Ut-Dn for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:03 -0500 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-389-os4guXI0Mb6mx-a0s64ilw-1; Mon, 09 Dec 2024 07:38:00 -0500 Received: by mail-wr1-f71.google.com with SMTP id ffacd0b85a97d-3862c67763dso1815896f8f.3 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:38:00 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3861ecf4119sm12925315f8f.14.2024.12.09.04.37.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:37:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747881; 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=aQQh40wwBPdVycCz9xzGGWLkoYV4qfuAlbHWnwDiqjM=; b=CbT70MR8yMK5ok4IVwmrq0nDrUXcgq/9DAJQKbd3Q8Ee0v+6N8KsHAmFiYj2TvFxBrGKXT kpsVu691UHSuQhy93bLtMFx1UvEQ3CtRboCw3+k21iXlpBMxz8Aqn9l0PIYnk69h25vZ1S kpTgSFMdCnjPmSUPntyBlUuDypKjyXA= X-MC-Unique: os4guXI0Mb6mx-a0s64ilw-1 X-Mimecast-MFC-AGG-ID: os4guXI0Mb6mx-a0s64ilw X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747879; x=1734352679; 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=aQQh40wwBPdVycCz9xzGGWLkoYV4qfuAlbHWnwDiqjM=; b=EZfpRPDL2Wqdw4+Xae5Dx+CMnn8In7fIkSpQRdSSrySUSg3LLhrAO7N3rVhb9cgZ3Q 5vSN7H3sf46h34AoKZdgHQYfFUPW5PWL8glXT1NImT/MtbmpzeqOCG8OigSkxPBONQPg 0VV6MUyII/PYtaoArNyHTAUFuWrU/ED9sbKCOiEQYOjszMfR5sqiUsDizLoquvMO4O4d 05u/zQyn5/tfJ748QHruWsuqfDsmzNY41r/W2mpqYKKMGBSxdXlh/OXYpCetD/bZBBfr agyuJ+D+M24oU/JHjr2a0/ZlCbG6JLuNWZcYItSp7zWSEkGciB0/xOiatnOl/1nED1iD gG6w== X-Gm-Message-State: AOJu0YxSh7NcKJMoXY3d104TFqd54PqLde05Y/1QcoS7y0Jpb81xczVu hiPIKxlVmf8ZcyA4+UDYVpN9etmNvyDBwrFr05xGTwGfVzQJcsZQLnP1wWOhzI9aRY2fDP8Woas 9MPHOhfjj1vryGVa+bWMb2+rYHMNAQyHUVg/6hOBHUjP25+85S9QNty7fuZ6D906yUGuH7j3UXl 5RZz8fBudvhQh7Hm450ZFY0MRGcjrkyXGvE2HV X-Gm-Gg: ASbGncvX9HWCgCLz9uELQxeZ/LepDjdtPmEMG1rJBqAuHHAQRBvhuI7mNqFHxAWGFE+ 04Ve+wjzwnJtbnQP4xtFfW2Uu3vx7njdIgNw4a5r7HCWBALhqAs4wL7VPHniJNpf7DW/ylN0zoU fYDW5JF+B8+GJSCvnGM9vkZX0GFuZNQJqGCuTbrnhWFzQrVIodL+OwH+E1mtVaudW95LB/ghrFY 56ARU3pea4982N9OHtyHWfIcwHJQZEWw9REWzaaRGmzMqPrlbKYlA== X-Received: by 2002:a05:6000:144a:b0:385:f8bd:6e80 with SMTP id ffacd0b85a97d-3862b3e4458mr10190703f8f.56.1733747878846; Mon, 09 Dec 2024 04:37:58 -0800 (PST) X-Google-Smtp-Source: AGHT+IGzFTifBSYSzW3fJ6voGMUSVISIXLUfyNsk7svSndINudfaxbHG86MfKOEGzZf1d1Bacsuo1w== X-Received: by 2002:a05:6000:144a:b0:385:f8bd:6e80 with SMTP id ffacd0b85a97d-3862b3e4458mr10190680f8f.56.1733747878378; Mon, 09 Dec 2024 04:37:58 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 16/26] rust: qom: change the parent type to an associated type Date: Mon, 9 Dec 2024 13:37:07 +0100 Message-ID: <20241209123717.99077-17-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733748432357116600 Content-Type: text/plain; charset="utf-8" Avoid duplicated code to retrieve the QOM type strings from the Rust type. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Zhao Liu <zhao1.liu@intel.com> --- rust/hw/char/pl011/src/device.rs | 6 ++++-- rust/qemu-api/src/definitions.rs | 8 ++------ rust/qemu-api/tests/tests.rs | 3 +-- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index 0ab825b1ca4..3e29442a625 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -113,7 +113,8 @@ unsafe impl ObjectType for PL011State { } =20 impl ObjectImpl for PL011State { - const PARENT_TYPE_NAME: Option<&'static CStr> =3D Some(<SysBusDevice a= s ObjectType>::TYPE_NAME); + type ParentType =3D SysBusDevice; + const INSTANCE_INIT: Option<unsafe fn(&mut Self)> =3D Some(Self::init); } =20 @@ -650,7 +651,8 @@ unsafe impl ObjectType for PL011Luminary { } =20 impl ObjectImpl for PL011Luminary { - const PARENT_TYPE_NAME: Option<&'static CStr> =3D Some(<PL011State as = ObjectType>::TYPE_NAME); + type ParentType =3D PL011State; + const INSTANCE_INIT: Option<unsafe fn(&mut Self)> =3D Some(Self::init); } =20 diff --git a/rust/qemu-api/src/definitions.rs b/rust/qemu-api/src/definitio= ns.rs index 1c412dbc876..1975ad91867 100644 --- a/rust/qemu-api/src/definitions.rs +++ b/rust/qemu-api/src/definitions.rs @@ -57,7 +57,7 @@ pub unsafe trait ObjectType: Sized { pub trait ObjectImpl: ObjectType + ClassInitImpl { /// The parent of the type. This should match the first field of /// the struct that implements `ObjectImpl`: - const PARENT_TYPE_NAME: Option<&'static CStr>; + type ParentType: ObjectType; =20 /// Whether the object can be instantiated const ABSTRACT: bool =3D false; @@ -76,11 +76,7 @@ pub trait ObjectImpl: ObjectType + ClassInitImpl { =20 const TYPE_INFO: TypeInfo =3D TypeInfo { name: Self::TYPE_NAME.as_ptr(), - parent: if let Some(pname) =3D Self::PARENT_TYPE_NAME { - pname.as_ptr() - } else { - core::ptr::null_mut() - }, + parent: Self::ParentType::TYPE_NAME.as_ptr(), instance_size: core::mem::size_of::<Self>(), instance_align: core::mem::align_of::<Self>(), instance_init: match Self::INSTANCE_INIT { diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index 1be03eb685c..2a72b0f9276 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -53,8 +53,7 @@ unsafe impl ObjectType for DummyState { } =20 impl ObjectImpl for DummyState { - const PARENT_TYPE_NAME: Option<&'static CStr> =3D - Some(<DeviceState as ObjectType>::TYPE_NAME); + type ParentType =3D DeviceState; const ABSTRACT: bool =3D false; } =20 --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733748045; cv=none; d=zohomail.com; s=zohoarc; b=g3FvKeCu8PRF9n1XA6iFpArehvajl7XCLYvyCK93iUVItFRzsqipCdyTuxZkGYIAUKofrWBdi+Hv8V8ZhZ5UciyqEnqeN7bSAguZyxaO3Yye7Vzay/AnQx7cMqmS5dEISEeAwAopBSwD5fEHZlaiidQljAQZW/1CpQ1EOl/K+EM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733748045; 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=5VQgmvbl2HSJ8RCTUzTR6hdmu5/vqQaEfjawIXvHjxA=; b=QzsHUMOEZRZ/xlFR2rb+epoP1YCRBo1lX8vESiz6GwKZV80f/c+14rd2F5k2C0XmnBqXNeRwayjKxfwQEVIly2MYlgsyJaDOy6/l/wmpsyclCxI/s16XUG1q6Lzt/W7Ko/ua1Bt98KmJkAIT2gZCNItDQu8no/yTvRiMEPmj/yA= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733748045715425.2210901947029; Mon, 9 Dec 2024 04:40:45 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd39-0005eK-F0; Mon, 09 Dec 2024 07:39:44 -0500 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 <pbonzini@redhat.com>) id 1tKd1d-00044Z-OL for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:12 -0500 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 <pbonzini@redhat.com>) id 1tKd1Z-0007VG-Lm for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:08 -0500 Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-34-rNlAtMULP-WKdfMd0Wz05w-1; Mon, 09 Dec 2024 07:38:03 -0500 Received: by mail-wm1-f71.google.com with SMTP id 5b1f17b1804b1-434ed70b74eso14940715e9.1 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:38:03 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-434f5800218sm31418055e9.1.2024.12.09.04.37.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:37:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747885; 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=5VQgmvbl2HSJ8RCTUzTR6hdmu5/vqQaEfjawIXvHjxA=; b=N0kdeC3Hs8sikQ3wDRfwVcisPSz9hyw8oUJ5c64qisJKlNGXnHSOXrNourkUORqvTFwMMq /LEAKn/aAPxkewndO2T3F1fAUsISZ3wd2UrbkxRD4aSQX7JjJB4aWxtxlKYrg5ITx6UYSZ kaOxcx4CqniLh+jY5e2sBXmisUBacgg= X-MC-Unique: rNlAtMULP-WKdfMd0Wz05w-1 X-Mimecast-MFC-AGG-ID: rNlAtMULP-WKdfMd0Wz05w X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747881; x=1734352681; 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=5VQgmvbl2HSJ8RCTUzTR6hdmu5/vqQaEfjawIXvHjxA=; b=KC56XO6Y6UrSygR47IuFeX27nNIIxoCwGDYnQ3j49xf8I9d1frS8CjlmnZzyWKxD75 do62hAp7PsU8dPzUqYeT7a9+dgLOwbqHhxofsGVA7YYuikispxFOg5QBBGC+Mbi8bc63 E33TyjxhqkyJEcoWnuMWKdqP9ArE+rvVpbeLsoene97hmD+0JbHQ5h59bchQkCqXA5pJ DKRPSy8QfNIGcjEuzs53rNo3D456p6NRJufUMY7C3/UH9XjCHOl08lCve0orYRVpYkoJ c9nKIgqglljvgpiJRZh7UYVJ5r2BaDbUJwlgBGiCOPfEesey5bxEZuChtXxubLgdmGO6 NZ8A== X-Gm-Message-State: AOJu0YzOeu5apufX0FEsME8Sj2DGugAR4xzUes6yku6cEx8lbR3jlirt 6YY/zq9MfiGMB+8JijYo5FfwE3BPfqdLO+lUsU89k06GsXww+Nd0tEHTeBU4l9b0Su4MXBoKgZD pUDkbuVd572vuKa/4FNtBpYkVFxMxLjEnGVTg7fimhCXpqUoDGHFY9/ml1y50ZuTU6mqcCiplbA N3Fxf6So/1Zh5TtHW6907py4MaPigEpzFr1/P0 X-Gm-Gg: ASbGncvZPHZSRr2iqXKxFxRVTwfjvNGg/iocNEX5V7fID+MYmdXb0gwQF0dss4o9FIp nx92l9nFIcMWaN1ZLJOZC7QEnOHF42QOTpFL7gbARBlw2B4bNvtPk/h0lq/NwSYX8s5KDjppwmG ZaxS4/xAxYmjsb4ug4bwtzeVdfIMAeVs2Gejur/86K7vDEzs7+Q+i/21PYV0dWOxS58byMzx70o 5iCWJAwpkHog3A4lZ1E57OhIM+L3eXyiU94UKKEucPTcFthZgqBxQ== X-Received: by 2002:a05:600c:4e8d:b0:434:ff25:199f with SMTP id 5b1f17b1804b1-434ff251ef2mr6415495e9.26.1733747881069; Mon, 09 Dec 2024 04:38:01 -0800 (PST) X-Google-Smtp-Source: AGHT+IGKcEJwCHui4xK1W5JD0e13Z86WVRuTNq8duGsIkBltSl9/dFcBDgG28q/fS5bkhYlQSvvcFg== X-Received: by 2002:a05:600c:4e8d:b0:434:ff25:199f with SMTP id 5b1f17b1804b1-434ff251ef2mr6415235e9.26.1733747880464; Mon, 09 Dec 2024 04:38:00 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 17/26] rust: qom: put class_init together from multiple ClassInitImpl<> Date: Mon, 9 Dec 2024 13:37:08 +0100 Message-ID: <20241209123717.99077-18-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733748046762116600 Content-Type: text/plain; charset="utf-8" Parameterize the implementation of ClassInitImpl so that it is possible to call up the chain of implementations, one superclass at a time starting at ClassInitImpl<Self::Class>. In order to avoid having to implement (for example) ClassInitImpl<PL011Class>, also remove the dummy PL011Class and PL011LuminaryClass structs and specify the same ObjectType::Class as the superclass. In the future this default behavior can be handled by a procedural macro, by looking at the first field in the struct. Note that the new trait is safe: the calls are started by rust_class_init<>(), which is not public and can convert the class pointer to a Rust reference. Since CLASS_BASE_INIT applies to the type that is being defined, and only to it, move it to ObjectImpl. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Zhao Liu <zhao1.liu@intel.com> --- rust/hw/char/pl011/src/device.rs | 19 +------ rust/qemu-api/src/definitions.rs | 85 +++++++++++++++++++++++-------- rust/qemu-api/src/device_class.rs | 50 +++++++----------- rust/qemu-api/src/sysbus.rs | 18 ++++++- rust/qemu-api/tests/tests.rs | 9 +--- 5 files changed, 101 insertions(+), 80 deletions(-) diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index 3e29442a625..d9e9f35f456 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -13,7 +13,6 @@ c_str, definitions::ObjectImpl, device_class::DeviceImpl, - impl_device_class, irq::InterruptSource, prelude::*, }; @@ -108,7 +107,7 @@ pub struct PL011State { } =20 unsafe impl ObjectType for PL011State { - type Class =3D PL011Class; + type Class =3D <SysBusDevice as ObjectType>::Class; const TYPE_NAME: &'static CStr =3D crate::TYPE_PL011; } =20 @@ -118,11 +117,6 @@ impl ObjectImpl for PL011State { const INSTANCE_INIT: Option<unsafe fn(&mut Self)> =3D Some(Self::init); } =20 -#[repr(C)] -pub struct PL011Class { - _inner: [u8; 0], -} - impl DeviceImpl for PL011State { fn properties() -> &'static [Property] { &device_class::PL011_PROPERTIES @@ -134,8 +128,6 @@ fn vmsd() -> Option<&'static VMStateDescription> { const RESET: Option<fn(&mut Self)> =3D Some(Self::reset); } =20 -impl_device_class!(PL011State); - impl PL011State { /// Initializes a pre-allocated, unitialized instance of `PL011State`. /// @@ -627,11 +619,6 @@ pub struct PL011Luminary { parent_obj: PL011State, } =20 -#[repr(C)] -pub struct PL011LuminaryClass { - _inner: [u8; 0], -} - impl PL011Luminary { /// Initializes a pre-allocated, unitialized instance of `PL011Luminar= y`. /// @@ -646,7 +633,7 @@ unsafe fn init(&mut self) { } =20 unsafe impl ObjectType for PL011Luminary { - type Class =3D PL011LuminaryClass; + type Class =3D <PL011State as ObjectType>::Class; const TYPE_NAME: &'static CStr =3D crate::TYPE_PL011_LUMINARY; } =20 @@ -657,5 +644,3 @@ impl ObjectImpl for PL011Luminary { } =20 impl DeviceImpl for PL011Luminary {} - -impl_device_class!(PL011Luminary); diff --git a/rust/qemu-api/src/definitions.rs b/rust/qemu-api/src/definitio= ns.rs index 1975ad91867..2429b9f53f0 100644 --- a/rust/qemu-api/src/definitions.rs +++ b/rust/qemu-api/src/definitions.rs @@ -33,6 +33,16 @@ unsafe { std::ptr::drop_in_place(obj.cast::<T>()) } } =20 +unsafe extern "C" fn rust_class_init<T: ObjectType + ClassInitImpl<T::Clas= s>>( + klass: *mut ObjectClass, + _data: *mut c_void, +) { + // SAFETY: klass is a T::Class, since rust_class_init<T> + // is called from QOM core as the class_init function + // for class T + T::class_init(unsafe { &mut *klass.cast::<T::Class>() }) +} + /// Trait exposed by all structs corresponding to QOM objects. /// /// # Safety @@ -45,7 +55,8 @@ /// - the first field of the struct must be of the instance struct corresp= onding /// to the superclass declared in the `TypeInfo` pub unsafe trait ObjectType: Sized { - /// The QOM class object corresponding to this struct. Not used yet. + /// The QOM class object corresponding to this struct. This is used + /// to automatically generate a `class_init` method. type Class; =20 /// The name of the type, which can be passed to `object_new()` to @@ -54,7 +65,7 @@ pub unsafe trait ObjectType: Sized { } =20 /// Trait a type must implement to be registered with QEMU. -pub trait ObjectImpl: ObjectType + ClassInitImpl { +pub trait ObjectImpl: ObjectType + ClassInitImpl<Self::Class> { /// The parent of the type. This should match the first field of /// the struct that implements `ObjectImpl`: type ParentType: ObjectType; @@ -74,6 +85,15 @@ pub trait ObjectImpl: ObjectType + ClassInitImpl { /// `INSTANCE_INIT` functions have been called. const INSTANCE_POST_INIT: Option<fn(&mut Self)> =3D None; =20 + /// Called on descendent classes after all parent class initialization + /// has occurred, but before the class itself is initialized. This + /// is only useful if a class is not a leaf, and can be used to undo + /// the effects of copying the contents of the parent's class struct + /// to the descendants. + const CLASS_BASE_INIT: Option< + unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void), + > =3D None; + const TYPE_INFO: TypeInfo =3D TypeInfo { name: Self::TYPE_NAME.as_ptr(), parent: Self::ParentType::TYPE_NAME.as_ptr(), @@ -90,37 +110,60 @@ pub trait ObjectImpl: ObjectType + ClassInitImpl { instance_finalize: Some(drop_object::<Self>), abstract_: Self::ABSTRACT, class_size: core::mem::size_of::<Self::Class>(), - class_init: <Self as ClassInitImpl>::CLASS_INIT, - class_base_init: <Self as ClassInitImpl>::CLASS_BASE_INIT, + class_init: Some(rust_class_init::<Self>), + class_base_init: Self::CLASS_BASE_INIT, class_data: core::ptr::null_mut(), interfaces: core::ptr::null_mut(), }; } =20 -/// Trait used to fill in a class struct. +/// Internal trait used to automatically fill in a class struct. /// /// Each QOM class that has virtual methods describes them in a /// _class struct_. Class structs include a parent field corresponding /// to the vtable of the parent class, all the way up to [`ObjectClass`]. -/// Each QOM type has one such class struct. +/// Each QOM type has one such class struct; this trait takes care of +/// initializing the `T` part of the class struct, for the type that +/// implements the trait. /// -/// The Rust implementation of methods will usually come from a trait -/// like [`ObjectImpl`] or [`DeviceImpl`](crate::device_class::DeviceImpl). -pub trait ClassInitImpl { - /// Function that is called after all parent class initialization - /// has occurred. On entry, the virtual method pointers are set to +/// Each struct will implement this trait with `T` equal to each +/// superclass. For example, a device should implement at least +/// `ClassInitImpl<`[`DeviceClass`](crate::bindings::DeviceClass)`>`. +/// +/// Fortunately, this is almost never necessary. Instead, the Rust +/// implementation of methods will usually come from a trait like +/// [`ObjectImpl`] or [`DeviceImpl`](crate::device_class::DeviceImpl). +/// `ClassInitImpl` then can be provided by blanket implementations +/// that operate on all implementors of the `*Impl`* trait. For example: +/// +/// ```ignore +/// impl<T> ClassInitImpl<DeviceClass> for T +/// where +/// T: DeviceImpl, +/// ``` +/// +/// The only case in which a manual implementation of the trait is needed +/// is for interfaces (note that there is no Rust example yet for using +/// interfaces). In this case, unlike the C case, the Rust class _has_ +/// to define its own class struct `FooClass` to go together with +/// `ClassInitImpl<FooClass>`. +pub trait ClassInitImpl<T> { + /// Initialize `klass` to point to the virtual method implementations + /// for `Self`. On entry, the virtual method pointers are set to /// the default values coming from the parent classes; the function /// can change them to override virtual methods of a parent class. - const CLASS_INIT: Option<unsafe extern "C" fn(klass: *mut ObjectClass,= data: *mut c_void)>; - - /// Called on descendent classes after all parent class initialization - /// has occurred, but before the class itself is initialized. This - /// is only useful if a class is not a leaf, and can be used to undo - /// the effects of copying the contents of the parent's class struct - /// to the descendants. - const CLASS_BASE_INIT: Option< - unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void), - >; + /// + /// The virtual method implementations usually come from another + /// trait, for example [`DeviceImpl`](crate::device_class::DeviceImpl) + /// when `T` is [`DeviceClass`](crate::bindings::DeviceClass). + /// + /// On entry, `klass`'s parent class is initialized, while the other f= ields + /// are all zero; it is therefore assumed that all fields in `T` can be + /// zeroed, otherwise it would not be possible to provide the class as= a + /// `&mut T`. TODO: add a bound of [`Zeroable`](crate::zeroable::Zero= able) + /// to T; this is more easily done once Zeroable does not require a ma= nual + /// implementation (Rust 1.75.0). + fn class_init(klass: &mut T); } =20 #[macro_export] diff --git a/rust/qemu-api/src/device_class.rs b/rust/qemu-api/src/device_c= lass.rs index 03d03feee83..ee9ae7eeb74 100644 --- a/rust/qemu-api/src/device_class.rs +++ b/rust/qemu-api/src/device_class.rs @@ -2,10 +2,11 @@ // Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org> // SPDX-License-Identifier: GPL-2.0-or-later =20 -use std::{ffi::CStr, os::raw::c_void}; +use std::ffi::CStr; =20 use crate::{ - bindings::{self, DeviceClass, DeviceState, Error, ObjectClass, Propert= y, VMStateDescription}, + bindings::{self, DeviceClass, DeviceState, Error, Property, VMStateDes= cription}, + definitions::ClassInitImpl, prelude::*, zeroable::Zeroable, }; @@ -45,7 +46,7 @@ fn vmsd() -> Option<&'static VMStateDescription> { /// # Safety /// /// This function is only called through the QOM machinery and -/// the `impl_device_class!` macro. +/// used by the `ClassInitImpl<DeviceClass>` trait. /// We expect the FFI user of this function to pass a valid pointer that /// can be downcasted to type `T`. We also expect the device is /// readable/writeable from one thread at any time. @@ -66,43 +67,26 @@ fn vmsd() -> Option<&'static VMStateDescription> { T::RESET.unwrap()(unsafe { &mut *state }); } =20 -/// # Safety -/// -/// We expect the FFI user of this function to pass a valid pointer that -/// can be downcasted to type `DeviceClass`, because `T` implements -/// `DeviceImpl`. -pub unsafe extern "C" fn rust_device_class_init<T: DeviceImpl>( - klass: *mut ObjectClass, - _: *mut c_void, -) { - let mut dc =3D ::core::ptr::NonNull::new(klass.cast::<DeviceClass>()).= unwrap(); - unsafe { - let dc =3D dc.as_mut(); +impl<T> ClassInitImpl<DeviceClass> for T +where + T: DeviceImpl, +{ + fn class_init(dc: &mut DeviceClass) { if <T as DeviceImpl>::REALIZE.is_some() { dc.realize =3D Some(rust_realize_fn::<T>); } if <T as DeviceImpl>::RESET.is_some() { - bindings::device_class_set_legacy_reset(dc, Some(rust_reset_fn= ::<T>)); + unsafe { + bindings::device_class_set_legacy_reset(dc, Some(rust_rese= t_fn::<T>)); + } } if let Some(vmsd) =3D <T as DeviceImpl>::vmsd() { dc.vmsd =3D vmsd; } - bindings::device_class_set_props(dc, <T as DeviceImpl>::properties= ().as_ptr()); - } -} - -#[macro_export] -macro_rules! impl_device_class { - ($type:ty) =3D> { - impl $crate::definitions::ClassInitImpl for $type { - const CLASS_INIT: Option< - unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut := :std::os::raw::c_void), - > =3D Some($crate::device_class::rust_device_class_init::<$typ= e>); - const CLASS_BASE_INIT: Option< - unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut := :std::os::raw::c_void), - > =3D None; + unsafe { + bindings::device_class_set_props(dc, <T as DeviceImpl>::proper= ties().as_ptr()); } - }; + } } =20 #[macro_export] @@ -147,8 +131,8 @@ macro_rules! declare_properties { }; } =20 -unsafe impl ObjectType for bindings::DeviceState { - type Class =3D bindings::DeviceClass; +unsafe impl ObjectType for DeviceState { + type Class =3D DeviceClass; const TYPE_NAME: &'static CStr =3D unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_DEVICE= ) }; } diff --git a/rust/qemu-api/src/sysbus.rs b/rust/qemu-api/src/sysbus.rs index 5ee068541cf..5d15b317405 100644 --- a/rust/qemu-api/src/sysbus.rs +++ b/rust/qemu-api/src/sysbus.rs @@ -6,7 +6,13 @@ =20 pub use bindings::{SysBusDevice, SysBusDeviceClass}; =20 -use crate::{bindings, cell::bql_locked, irq::InterruptSource, prelude::*}; +use crate::{ + bindings::{self, DeviceClass}, + cell::bql_locked, + definitions::ClassInitImpl, + irq::InterruptSource, + prelude::*, +}; =20 unsafe impl ObjectType for SysBusDevice { type Class =3D SysBusDeviceClass; @@ -14,6 +20,16 @@ unsafe impl ObjectType for SysBusDevice { unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_SYS_BU= S_DEVICE) }; } =20 +// TODO: add SysBusDeviceImpl +impl<T> ClassInitImpl<SysBusDeviceClass> for T +where + T: ClassInitImpl<DeviceClass>, +{ + fn class_init(sdc: &mut SysBusDeviceClass) { + <T as ClassInitImpl<DeviceClass>>::class_init(&mut sdc.parent_clas= s); + } +} + impl SysBusDevice { /// Return `self` cast to a mutable pointer, for use in calls to C cod= e. const fn as_mut_ptr(&self) -> *mut SysBusDevice { diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index 2a72b0f9276..4ce1bd19247 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -31,11 +31,6 @@ pub struct DummyState { pub migrate_clock: bool, } =20 - #[repr(C)] - pub struct DummyClass { - pub _parent: DeviceClass, - } - declare_properties! { DUMMY_PROPERTIES, define_property!( @@ -48,7 +43,7 @@ pub struct DummyClass { } =20 unsafe impl ObjectType for DummyState { - type Class =3D DummyClass; + type Class =3D <DeviceState as ObjectType>::Class; const TYPE_NAME: &'static CStr =3D c_str!("dummy"); } =20 @@ -66,8 +61,6 @@ fn vmsd() -> Option<&'static VMStateDescription> { } } =20 - impl_device_class!(DummyState); - unsafe { module_call_init(module_init_type::MODULE_INIT_QOM); object_unref(object_new(DummyState::TYPE_NAME.as_ptr()).cast()); --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733748655; cv=none; d=zohomail.com; s=zohoarc; b=jri7TdKhCX89t3RLve3b+iMzvpcBVu/XnJXPqw0wCbqz0x0uT79UoHvVEM4uSOezp2Cr7Q9ZIJv1fXtbrWy/nrotdDSSZaNJeaCo082PzE9B2LR7UmVVKL4k+N70H69G/EErvfIA9fIrCrCseSkuri52ddU2RJu+UUJjZ8xXIxs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733748655; 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=BQvprRtOhbO0tTAhGCjhk7/MAt2yyWFqpYjv7MQU8PQ=; b=ADUHInfm318NIDRfa/+zpTYvDFK8kggWgvOBP3CMA0/7paNMS5YZUYuAg3UjQiE9E0a2QKGP5zUw7C0Co1tKfmaVqk7MCvcdKPr9DfI9JQsdLTKYTt4OeeRVgJWDjZ0EhgGbuYe2uvewXhz7QpZNkbv8EaraJITOxnBRp0N+Izw= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733748655900839.3473154422852; Mon, 9 Dec 2024 04:50:55 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd7G-0000Xl-UG; Mon, 09 Dec 2024 07:43:59 -0500 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 <pbonzini@redhat.com>) id 1tKd2h-0004u0-UH for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:39:17 -0500 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 <pbonzini@redhat.com>) id 1tKd2f-0007l3-RN for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:39:15 -0500 Received: from mail-wm1-f70.google.com (mail-wm1-f70.google.com [209.85.128.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-574-DBsfOBzgMYuc_CTdoHEtlw-1; Mon, 09 Dec 2024 07:38:05 -0500 Received: by mail-wm1-f70.google.com with SMTP id 5b1f17b1804b1-434f3a758dbso9978515e9.0 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:38:05 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-434f123da83sm71056725e9.29.2024.12.09.04.38.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:38:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747952; 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=BQvprRtOhbO0tTAhGCjhk7/MAt2yyWFqpYjv7MQU8PQ=; b=A103eHvk8p3TOcsxM55Amz/m9+oIUTNs0umFJT/R7td50vOZdi75q02XV0EChYCUupU14c X0vdMhGS81+byFsOiVheEuBj8pxdSet43mQ//s1RYZtoYw+vgFWmqJ2T4NwAtzpe6XZDBs came6yJnoagHGq1BUd0YoNdcoR7Suek= X-MC-Unique: DBsfOBzgMYuc_CTdoHEtlw-1 X-Mimecast-MFC-AGG-ID: DBsfOBzgMYuc_CTdoHEtlw X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747884; x=1734352684; 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=BQvprRtOhbO0tTAhGCjhk7/MAt2yyWFqpYjv7MQU8PQ=; b=U0P+n6JlI8mHJLNSYyErMY0+wSLWj26+V4YXx3cOgoS/Iby+5Ds+HBcZQzm8wy+oGb w9HWdFPqLDdAZRF2XDG3jm4vbCUc/NUSuGDYGC6hv7CjsW3ZgCrX5zidLNzeLPvrG0OA 8ft7pIt4c5FOfCKVbOecOlbxs+JoYU4Ybg5oUNZ6AZavEy1vcaGQgq27X1C779GLj9wT FplAYqYqqxj5d8ZH+RqX2xXv7kQKJS8FekEhifnGivIEFKRv6tFpfS8z8eAal1DZPhGM a+bFzBFMrAc05mAuV6H0c+PiZfwVPdAffgcVFWTKlnbpxvaneFYtH+YUw373vyfYGe64 9E5g== X-Gm-Message-State: AOJu0YxGfOng0dulCtL1c1Jr+eyAThwMn/bd7pKEmGCNRPJJ9BoiBmzX 1ooPEtokkhUzsTo3K86MUzdUh502NuiuY8rxZxdu7TN7anpAHL6GEbyBU59P7Vm9eUzUWdASN88 MhooOehsNdB026CuYml/Kmq7ZwQpmanqVNf7SnHlFL4S6QjX2ZXtWfrYHconLux9yY516RmAvmC vYymMCCjUYj46FRw5UgbHZ5AylTgIwxyqZTXyH X-Gm-Gg: ASbGncvqH9D6yBOxtM0IsA0rllITGKZhKWQttAWvKYEulDGe08BoBlAJp9A1VtVWVji W8IpVRFYelSN0NvnYKki5ImdpVTQpi/izj5arAUU1unC5EMCa3uThIGCnncvB/uFyYX1Xk27urX I1zjPtt8LpXN7syd46+mcSX698nXDIHBqN0UJpCzIoqC44b44QgKlgx9xq/F/tJzSi45LUHQZVW +2uAEFl/fgHGxO7i052sS4EyvwkPxdTvo/WbqJYIk9TVW+FqiSWZw== X-Received: by 2002:a05:600c:4f0d:b0:434:f0ab:42f with SMTP id 5b1f17b1804b1-434fff9c4bfmr2869905e9.20.1733747883727; Mon, 09 Dec 2024 04:38:03 -0800 (PST) X-Google-Smtp-Source: AGHT+IH55kiSw1XmRwkB3SlPJ0tg4JF7UgX1BMHGNFvQ8Jlk8je4ljZuKXqY9kQUzOVhz9TJZAW5uA== X-Received: by 2002:a05:600c:4f0d:b0:434:f0ab:42f with SMTP id 5b1f17b1804b1-434fff9c4bfmr2869675e9.20.1733747883265; Mon, 09 Dec 2024 04:38:03 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 18/26] rust: qom: add possibility of overriding unparent Date: Mon, 9 Dec 2024 13:37:09 +0100 Message-ID: <20241209123717.99077-19-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=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: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733748657329116600 Content-Type: text/plain; charset="utf-8" Add a blanket definition of ClassInitImpl<ObjectClass> that thunks ObjectImpl::UNPARENT and overrides it in ObjectClass if it is not None. ClassInitImpl<DeviceClass> can now call its superclass's ClassInitImpl, so that the C and Rust hierarchies match more closely. This is mostly done as an example of implementing the metaclass hierarchy under ClassInitImpl. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Zhao Liu <zhao1.liu@intel.com> --- rust/qemu-api/src/definitions.rs | 44 ++++++++++++++++++++++++++++--- rust/qemu-api/src/device_class.rs | 6 +++-- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/rust/qemu-api/src/definitions.rs b/rust/qemu-api/src/definitio= ns.rs index 2429b9f53f0..958ea34decc 100644 --- a/rust/qemu-api/src/definitions.rs +++ b/rust/qemu-api/src/definitions.rs @@ -6,7 +6,7 @@ =20 use std::{ffi::CStr, os::raw::c_void}; =20 -use crate::bindings::{Object, ObjectClass, TypeInfo}; +use crate::bindings::{self, Object, ObjectClass, TypeInfo}; =20 unsafe extern "C" fn rust_instance_init<T: ObjectImpl>(obj: *mut Object) { // SAFETY: obj is an instance of T, since rust_instance_init<T> @@ -115,6 +115,9 @@ pub trait ObjectImpl: ObjectType + ClassInitImpl<Self::= Class> { class_data: core::ptr::null_mut(), interfaces: core::ptr::null_mut(), }; + + // methods on ObjectClass + const UNPARENT: Option<fn(&mut Self)> =3D None; } =20 /// Internal trait used to automatically fill in a class struct. @@ -128,7 +131,8 @@ pub trait ObjectImpl: ObjectType + ClassInitImpl<Self::= Class> { /// /// Each struct will implement this trait with `T` equal to each /// superclass. For example, a device should implement at least -/// `ClassInitImpl<`[`DeviceClass`](crate::bindings::DeviceClass)`>`. +/// `ClassInitImpl<`[`DeviceClass`](crate::bindings::DeviceClass)`>` and +/// `ClassInitImpl<`[`ObjectClass`](crate::bindings::ObjectClass)`>`. /// /// Fortunately, this is almost never necessary. Instead, the Rust /// implementation of methods will usually come from a trait like @@ -139,9 +143,13 @@ pub trait ObjectImpl: ObjectType + ClassInitImpl<Self:= :Class> { /// ```ignore /// impl<T> ClassInitImpl<DeviceClass> for T /// where -/// T: DeviceImpl, +/// T: ClassInitImpl<ObjectClass> + DeviceImpl, /// ``` /// +/// The bound on `ClassInitImpl<ObjectClass>` is needed so that, +/// after initializing the `DeviceClass` part of the class struct, +/// the parent [`ObjectClass`] is initialized as well. +/// /// The only case in which a manual implementation of the trait is needed /// is for interfaces (note that there is no Rust example yet for using /// interfaces). In this case, unlike the C case, the Rust class _has_ @@ -203,3 +211,33 @@ extern "C" fn ctor_fn() { } }; } + +/// # Safety +/// +/// We expect the FFI user of this function to pass a valid pointer that +/// can be downcasted to type `T`. We also expect the device is +/// readable/writeable from one thread at any time. +unsafe extern "C" fn rust_unparent_fn<T: ObjectImpl>(dev: *mut Object) { + unsafe { + assert!(!dev.is_null()); + let mut state =3D core::ptr::NonNull::new_unchecked(dev.cast::<T>(= )); + T::UNPARENT.unwrap()(state.as_mut()); + } +} + +impl<T> ClassInitImpl<ObjectClass> for T +where + T: ObjectImpl, +{ + fn class_init(oc: &mut ObjectClass) { + if <T as ObjectImpl>::UNPARENT.is_some() { + oc.unparent =3D Some(rust_unparent_fn::<T>); + } + } +} + +unsafe impl ObjectType for Object { + type Class =3D ObjectClass; + const TYPE_NAME: &'static CStr =3D + unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_OBJECT= ) }; +} diff --git a/rust/qemu-api/src/device_class.rs b/rust/qemu-api/src/device_c= lass.rs index ee9ae7eeb74..285dfe582c7 100644 --- a/rust/qemu-api/src/device_class.rs +++ b/rust/qemu-api/src/device_class.rs @@ -5,7 +5,7 @@ use std::ffi::CStr; =20 use crate::{ - bindings::{self, DeviceClass, DeviceState, Error, Property, VMStateDes= cription}, + bindings::{self, DeviceClass, DeviceState, Error, ObjectClass, Propert= y, VMStateDescription}, definitions::ClassInitImpl, prelude::*, zeroable::Zeroable, @@ -69,7 +69,7 @@ fn vmsd() -> Option<&'static VMStateDescription> { =20 impl<T> ClassInitImpl<DeviceClass> for T where - T: DeviceImpl, + T: ClassInitImpl<ObjectClass> + DeviceImpl, { fn class_init(dc: &mut DeviceClass) { if <T as DeviceImpl>::REALIZE.is_some() { @@ -86,6 +86,8 @@ fn class_init(dc: &mut DeviceClass) { unsafe { bindings::device_class_set_props(dc, <T as DeviceImpl>::proper= ties().as_ptr()); } + + <T as ClassInitImpl<ObjectClass>>::class_init(&mut dc.parent_class= ); } } =20 --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733748488; cv=none; d=zohomail.com; s=zohoarc; b=VFAy59zbjHOEToUT/91GkNiDbOsj15Woa0YmDybRIrMQJNcrEE13wAJ6uYulxwteapIF/5f7TpiyVgda44vqe1nSDm9ssbWdw408KJLakv50Iduiw/Bn1SPZ1QRiqVW7wpBJ70xzlSMEFeKIiXvwhOw6/5qaYE/RPF4pmYwrFe8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733748488; 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=AU4cR1A44Kzwr9V6X5ZqvFDrGfSGtRe4ER0j2E/bzHc=; b=R2wEYDQMVs1HYcuQvP32tS1FNQUEESHp1I1RUmFShDQkULjM6ZfmB+qywlC/Gml+KbF9TZip5pwT6NdFC/e0+0gL1a01U0TlxfenFGi0Oynsk4h2vhYiLoZJeiSuoGc7y6dLUlTd/uCW9mhRV0/ki3pK+Hp4iywp5617XjGi0X0= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733748488439770.1339761985837; Mon, 9 Dec 2024 04:48:08 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd4w-0007Xz-1e; Mon, 09 Dec 2024 07:41:37 -0500 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 <pbonzini@redhat.com>) id 1tKd1k-00046U-G0 for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:22 -0500 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 <pbonzini@redhat.com>) id 1tKd1f-0007WQ-Mz for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:16 -0500 Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-605-Cb_NfbdzOEC58wcGq7gr8g-1; Mon, 09 Dec 2024 07:38:08 -0500 Received: by mail-wm1-f71.google.com with SMTP id 5b1f17b1804b1-434f2cb3b4bso11475305e9.0 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:38:08 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-434d43b8557sm130234165e9.1.2024.12.09.04.38.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:38:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747890; 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=AU4cR1A44Kzwr9V6X5ZqvFDrGfSGtRe4ER0j2E/bzHc=; b=WfIha0+FuM2La1Jkvty9/+FH/Es4h0ZSZo2alf5lWIBAuKUjdMS6o4b2yi07w2pu2WZZTn GWrrZQ2U6CVQNPTDJcqjyyjr4nrnUrx4ILHV4SIOT36edtm9pQ/QEtx9tOReykFjkTKbsI IcsirJt31P5nm1vdYT8LgNtNm4OCW0s= X-MC-Unique: Cb_NfbdzOEC58wcGq7gr8g-1 X-Mimecast-MFC-AGG-ID: Cb_NfbdzOEC58wcGq7gr8g X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747886; x=1734352686; 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=AU4cR1A44Kzwr9V6X5ZqvFDrGfSGtRe4ER0j2E/bzHc=; b=Y6/DInLIrpshlbAYcz0n3XU2jvcUTBuElZq9nyOw4dAM10nN2r9Hw+DK+6W4ke3Lk2 X87IfxRlzA6696E021XbFiCnRp5DNTl5mmLFWnBptWwcd1+M2aQy3VhxAJ1cC/bGPp+y tV7jCV+gC76cAqwX4/DIWFZ1Oi73F2H4u/oweHxA05mlkwOoda/T3q2nSh9PmVQ6DwMt 3BNvFJsBAjA90LDp5KA78hKoSKoOMSI0dOjJ7zePW9aUMFSPiuZhKdoAPNNyl0qHXnmr Oyv2vi/AXWT7rjrbbSAXAD2Fv5w+hZbqmqEBJlypNgInLliJ7d7uBLTDJ/eWBAR3y9a+ /lXQ== X-Gm-Message-State: AOJu0Yw+2YbbAsRHImRfZd/R4b8TPJMMqosD9Yyns4x6IJYRXTVPlw16 HTlH9pg/MnFLsYUMaAb4+6jJhOOvuqaqLpy9ooBz0EmeZSiVXrm6RIFBzItMqunW9IY3ffBqK4v GYjxBjl6BEOpFOTpaRvFRUHZNhSbOGAhAi1n18n444A6wSx9FeyKjqQob1dYZxVC6iJawSYHVJ9 vA4aSPERp6kaouyDhUOWRUzPIEvIswrcy9i7ib X-Gm-Gg: ASbGnctDoF5iLxFodiWAxVnlvDfrCom2AX2HnENBK0dhRh5CklMFLVpHqbK+l7XGv5m 2CC9jXhOj0JBDvbCeDFnCQkNzaLjHyxh0pRPvHMudOMMXINSSnZcKiHuxo4ygcu3wVDUc8hCrck qmcFxLfwpkS7wRdWAw8mz8Q08toIc5rFeMyqsqLJZ6pRjQqLMdy0qn30iEzyCC9ynd5hgbxFtNe XtabiOWLH8iHja036FiUn8DhVTCpf9c9QW9ZaT5N/sQ5Uqj/fF57Q== X-Received: by 2002:a05:600c:1e12:b0:434:fd15:3adc with SMTP id 5b1f17b1804b1-434fd153f18mr13117025e9.25.1733747886153; Mon, 09 Dec 2024 04:38:06 -0800 (PST) X-Google-Smtp-Source: AGHT+IH792a2/w5pAGOwu2vIm8ipECAnESvUp2uFmPmy4nFPNNnT/IKjgVfrNZbB+CwJ2RXP4mmUZQ== X-Received: by 2002:a05:600c:1e12:b0:434:fd15:3adc with SMTP id 5b1f17b1804b1-434fd153f18mr13116705e9.25.1733747885593; Mon, 09 Dec 2024 04:38:05 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 19/26] rust: rename qemu-api modules to follow C code a bit more Date: Mon, 9 Dec 2024 13:37:10 +0100 Message-ID: <20241209123717.99077-20-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=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: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733748490569116600 Content-Type: text/plain; charset="utf-8" A full match would mean calling them qom::object and hw::core::qdev. For n= ow, keep the names shorter but still a bit easier to find. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Zhao Liu <zhao1.liu@intel.com> --- rust/hw/char/pl011/src/device.rs | 4 +- rust/qemu-api-macros/src/lib.rs | 2 +- rust/qemu-api/meson.build | 5 +- rust/qemu-api/src/lib.rs | 5 +- rust/qemu-api/src/module.rs | 43 +++++++++++ rust/qemu-api/src/prelude.rs | 2 +- .../qemu-api/src/{device_class.rs =3D> qdev.rs} | 4 +- rust/qemu-api/src/{definitions.rs =3D> qom.rs} | 74 +++++++++---------- rust/qemu-api/src/sysbus.rs | 2 +- rust/qemu-api/tests/tests.rs | 5 +- 10 files changed, 92 insertions(+), 54 deletions(-) create mode 100644 rust/qemu-api/src/module.rs rename rust/qemu-api/src/{device_class.rs =3D> qdev.rs} (97%) rename rust/qemu-api/src/{definitions.rs =3D> qom.rs} (83%) diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index d9e9f35f456..3fed8b4ad25 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -11,10 +11,10 @@ use qemu_api::{ bindings::{self, *}, c_str, - definitions::ObjectImpl, - device_class::DeviceImpl, irq::InterruptSource, prelude::*, + qdev::DeviceImpl, + qom::ObjectImpl, }; =20 use crate::{ diff --git a/rust/qemu-api-macros/src/lib.rs b/rust/qemu-api-macros/src/lib= .rs index cf99ac04b8f..74a8bc7503e 100644 --- a/rust/qemu-api-macros/src/lib.rs +++ b/rust/qemu-api-macros/src/lib.rs @@ -40,7 +40,7 @@ pub fn derive_object(input: TokenStream) -> TokenStream { let expanded =3D quote! { ::qemu_api::module_init! { MODULE_INIT_QOM =3D> unsafe { - ::qemu_api::bindings::type_register_static(&<#name as ::qe= mu_api::definitions::ObjectImpl>::TYPE_INFO); + ::qemu_api::bindings::type_register_static(&<#name as ::qe= mu_api::qom::ObjectImpl>::TYPE_INFO); } } }; diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build index adcee661150..7ff408ad68e 100644 --- a/rust/qemu-api/meson.build +++ b/rust/qemu-api/meson.build @@ -19,11 +19,12 @@ _qemu_api_rs =3D static_library( 'src/bitops.rs', 'src/cell.rs', 'src/c_str.rs', - 'src/definitions.rs', - 'src/device_class.rs', 'src/irq.rs', + 'src/module.rs', 'src/offset_of.rs', 'src/prelude.rs', + 'src/qdev.rs', + 'src/qom.rs', 'src/sysbus.rs', 'src/vmstate.rs', 'src/zeroable.rs', diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs index 9e007e16354..124bece0449 100644 --- a/rust/qemu-api/src/lib.rs +++ b/rust/qemu-api/src/lib.rs @@ -15,10 +15,11 @@ pub mod bitops; pub mod c_str; pub mod cell; -pub mod definitions; -pub mod device_class; pub mod irq; +pub mod module; pub mod offset_of; +pub mod qdev; +pub mod qom; pub mod sysbus; pub mod vmstate; pub mod zeroable; diff --git a/rust/qemu-api/src/module.rs b/rust/qemu-api/src/module.rs new file mode 100644 index 00000000000..fa5cea3598f --- /dev/null +++ b/rust/qemu-api/src/module.rs @@ -0,0 +1,43 @@ +// Copyright 2024, Linaro Limited +// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org> +// SPDX-License-Identifier: GPL-2.0-or-later + +//! Macro to register blocks of code that run as QEMU starts up. + +#[macro_export] +macro_rules! module_init { + ($type:ident =3D> $body:block) =3D> { + const _: () =3D { + #[used] + #[cfg_attr( + not(any(target_vendor =3D "apple", target_os =3D "windows"= )), + link_section =3D ".init_array" + )] + #[cfg_attr(target_vendor =3D "apple", link_section =3D "__DATA= ,__mod_init_func")] + #[cfg_attr(target_os =3D "windows", link_section =3D ".CRT$XCU= ")] + pub static LOAD_MODULE: extern "C" fn() =3D { + extern "C" fn init_fn() { + $body + } + + extern "C" fn ctor_fn() { + unsafe { + $crate::bindings::register_module_init( + Some(init_fn), + $crate::bindings::module_init_type::$type, + ); + } + } + + ctor_fn + }; + }; + }; + + // shortcut because it's quite common that $body needs unsafe {} + ($type:ident =3D> unsafe $body:block) =3D> { + $crate::module_init! { + $type =3D> { unsafe { $body } } + } + }; +} diff --git a/rust/qemu-api/src/prelude.rs b/rust/qemu-api/src/prelude.rs index 1b8677b2d9a..5cc41f081f9 100644 --- a/rust/qemu-api/src/prelude.rs +++ b/rust/qemu-api/src/prelude.rs @@ -7,4 +7,4 @@ pub use crate::cell::BqlCell; pub use crate::cell::BqlRefCell; =20 -pub use crate::definitions::ObjectType; +pub use crate::qom::ObjectType; diff --git a/rust/qemu-api/src/device_class.rs b/rust/qemu-api/src/qdev.rs similarity index 97% rename from rust/qemu-api/src/device_class.rs rename to rust/qemu-api/src/qdev.rs index 285dfe582c7..1228dabaaaf 100644 --- a/rust/qemu-api/src/device_class.rs +++ b/rust/qemu-api/src/qdev.rs @@ -2,12 +2,14 @@ // Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org> // SPDX-License-Identifier: GPL-2.0-or-later =20 +//! Bindings to create devices and access device functionality from Rust. + use std::ffi::CStr; =20 use crate::{ bindings::{self, DeviceClass, DeviceState, Error, ObjectClass, Propert= y, VMStateDescription}, - definitions::ClassInitImpl, prelude::*, + qom::ClassInitImpl, zeroable::Zeroable, }; =20 diff --git a/rust/qemu-api/src/definitions.rs b/rust/qemu-api/src/qom.rs similarity index 83% rename from rust/qemu-api/src/definitions.rs rename to rust/qemu-api/src/qom.rs index 958ea34decc..9b316e07efa 100644 --- a/rust/qemu-api/src/definitions.rs +++ b/rust/qemu-api/src/qom.rs @@ -2,7 +2,37 @@ // Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org> // SPDX-License-Identifier: GPL-2.0-or-later =20 -//! Definitions required by QEMU when registering a device. +//! Bindings to access QOM functionality from Rust. +//! +//! This module provides automatic creation and registration of `TypeInfo` +//! for classes that are written in Rust, and mapping between Rust traits +//! and QOM vtables. +//! +//! # Structure of a class +//! +//! A concrete class only needs a struct holding instance state. The struc= t must +//! implement the [`ObjectType`] and [`IsA`] traits, as well as any `*Impl` +//! traits provided by its superclasses. +//! +//! An abstract class will also provide a struct for instance data, with t= he +//! same characteristics as for concrete classes, but it also needs additi= onal +//! components to support virtual methods: +//! +//! * a struct for instance data, with the same characteristics as for con= crete +//! classes. +//! +//! * a struct for class data, for example `DeviceClass`. This corresponds= to +//! the C "class struct" and holds the vtable that is used by instances = of the +//! class and its subclasses. It must start with its parent's class stru= ct. +//! +//! * a trait for virtual method implementations, for example `DeviceImpl`. +//! Child classes implement this trait to provide their own behavior for +//! virtual methods. The trait's methods take `&self` to access instance= data. +//! +//! * an implementation of [`ClassInitImpl`], for example +//! `ClassInitImpl<DeviceClass>`. This fills the vtable in the class str= uct, +//! typically with wrappers that call into the +//! [`DeviceImpl`](crate::qdev::DeviceImpl) implementations. =20 use std::{ffi::CStr, os::raw::c_void}; =20 @@ -136,7 +166,7 @@ pub trait ObjectImpl: ObjectType + ClassInitImpl<Self::= Class> { /// /// Fortunately, this is almost never necessary. Instead, the Rust /// implementation of methods will usually come from a trait like -/// [`ObjectImpl`] or [`DeviceImpl`](crate::device_class::DeviceImpl). +/// [`ObjectImpl`] or [`DeviceImpl`](crate::qdev::DeviceImpl). /// `ClassInitImpl` then can be provided by blanket implementations /// that operate on all implementors of the `*Impl`* trait. For example: /// @@ -162,7 +192,7 @@ pub trait ClassInitImpl<T> { /// can change them to override virtual methods of a parent class. /// /// The virtual method implementations usually come from another - /// trait, for example [`DeviceImpl`](crate::device_class::DeviceImpl) + /// trait, for example [`DeviceImpl`](crate::qdev::DeviceImpl) /// when `T` is [`DeviceClass`](crate::bindings::DeviceClass). /// /// On entry, `klass`'s parent class is initialized, while the other f= ields @@ -174,44 +204,6 @@ pub trait ClassInitImpl<T> { fn class_init(klass: &mut T); } =20 -#[macro_export] -macro_rules! module_init { - ($type:ident =3D> $body:block) =3D> { - const _: () =3D { - #[used] - #[cfg_attr( - not(any(target_vendor =3D "apple", target_os =3D "windows"= )), - link_section =3D ".init_array" - )] - #[cfg_attr(target_vendor =3D "apple", link_section =3D "__DATA= ,__mod_init_func")] - #[cfg_attr(target_os =3D "windows", link_section =3D ".CRT$XCU= ")] - pub static LOAD_MODULE: extern "C" fn() =3D { - extern "C" fn init_fn() { - $body - } - - extern "C" fn ctor_fn() { - unsafe { - $crate::bindings::register_module_init( - Some(init_fn), - $crate::bindings::module_init_type::$type, - ); - } - } - - ctor_fn - }; - }; - }; - - // shortcut because it's quite common that $body needs unsafe {} - ($type:ident =3D> unsafe $body:block) =3D> { - $crate::module_init! { - $type =3D> { unsafe { $body } } - } - }; -} - /// # Safety /// /// We expect the FFI user of this function to pass a valid pointer that diff --git a/rust/qemu-api/src/sysbus.rs b/rust/qemu-api/src/sysbus.rs index 5d15b317405..fa69cadd7c1 100644 --- a/rust/qemu-api/src/sysbus.rs +++ b/rust/qemu-api/src/sysbus.rs @@ -9,9 +9,9 @@ use crate::{ bindings::{self, DeviceClass}, cell::bql_locked, - definitions::ClassInitImpl, irq::InterruptSource, prelude::*, + qom::ClassInitImpl, }; =20 unsafe impl ObjectType for SysBusDevice { diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index 4ce1bd19247..fc57eb81290 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -7,10 +7,9 @@ use qemu_api::{ bindings::*, c_str, declare_properties, define_property, - definitions::ObjectImpl, - device_class::DeviceImpl, - impl_device_class, prelude::*, + qdev::DeviceImpl, + qom::ObjectImpl, zeroable::Zeroable, }; =20 --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733748763; cv=none; d=zohomail.com; s=zohoarc; b=ELNj7Kwh4lhRScJ01SfxybfS1bYLZ4nhyft33+yNY6T4n6mLgDoreieUo+LzVXvpeUbaBxsaHFOZPBywQWjQHaL5ZSyof3Eocl0OoDSBKq+hQiNv81vfKdXxOJoSLvicM4uBnMXynnVg7qDgvXxIhDZH75pKbiBoXDvIOp7KAKQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733748763; 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=cmaMuh+/1R6nn1pVbFPg8WJblYj+VkUXSy659iDTG4g=; b=jzVdAofNSICmBdjdgqTYPsGV1TsLWLmDzmIqH4iafLxEvOeBwcipRU1TDnWavc2WhOIpB9cVnXWxD/dVo/jXThBvonvGlEYDCDioE83f3YL/E7XdiDuAbkCPR8oGSt35VfJotBW7e34upTu2fcG6sUbTMGoH80KjEYAkEiDRSk0= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 173374876346680.12211692030155; Mon, 9 Dec 2024 04:52:43 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd3b-000614-Cn; Mon, 09 Dec 2024 07:40:19 -0500 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 <pbonzini@redhat.com>) id 1tKd1i-00045t-D5 for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:20 -0500 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 <pbonzini@redhat.com>) id 1tKd1g-0007Wl-Dd for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:14 -0500 Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-306-4UmEr9RnPqe0HdP5bDF4Cg-1; Mon, 09 Dec 2024 07:38:10 -0500 Received: by mail-wm1-f71.google.com with SMTP id 5b1f17b1804b1-434fb9646efso5568575e9.1 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:38:10 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-434d527395csm189736155e9.17.2024.12.09.04.38.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:38:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747891; 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=cmaMuh+/1R6nn1pVbFPg8WJblYj+VkUXSy659iDTG4g=; b=JA3pDqT4MYv+ht8he5HPnzaY3jSz29KwELx2dHlbLyVrfkaInox0qrw4YBx+siC1XDFGoR EMm5heqpgr3FC/JPDvg7yPpxwLWvQTa2ho/nKT8zNAWLWvq/Bi3qlf+6zW080V+3uOxlQU oZC5b3Wt0ymBa1MlsdK/D0V5g0Vdua4= X-MC-Unique: 4UmEr9RnPqe0HdP5bDF4Cg-1 X-Mimecast-MFC-AGG-ID: 4UmEr9RnPqe0HdP5bDF4Cg X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747889; x=1734352689; 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=cmaMuh+/1R6nn1pVbFPg8WJblYj+VkUXSy659iDTG4g=; b=SRnnHHt+Nx3VPivoeIkEC/BDev32tKFsONOfj1icp9kxKA+ziegTvEjUhUGCx+fEul 0ABWvVGn4+/vglH3h76toQsQtRwq6XOQ19I4QXp1QzoRtHrUuxpCJSWJJoNgq+cKYsfj 2httYQwLOfaQkK0sSipFA2YD+nHvcVYb2kjprxmbm1Lba/RhA/YinXTOZTuPQhxCzyve aqwTOolE5Fk6kVwn3jeshgG4lzwwDnto1o0/nz/mWPFq29yx6fPdO2oh4KDAUOcXBOwb nP/RlIOviqhu9zQguGSrUqnh2HnCxfqqfqy0PDnnIrWJqS05PRJ7SVt1mJpz5IHOp5ZU 4BWw== X-Gm-Message-State: AOJu0YzIk69l0QNFY1iQdfirDi58pMNMHXJGDCAMvFyctvpLV3Ec1lcj CdZTqkWKr/u52f+xLXGSiibdtebVu5h/KlLWC32ySV9lcquC9I1uqBOgnrKH4LZJKn+X9CeLAPj XXnVZmkiefLZQcqSZ6+aPUP4c4wfIwkQOZ0xvx6ets4c5uzFLMX3RHdJAJRExvA4c1Dh9NoQi8y aSCVzmvfcTZL1V9AdXakMwka69Jkyxhx+pzlON X-Gm-Gg: ASbGncsMlJ7peHsLsmPQzYrcIe/qZvzCIuw8FRedCzn2MVZriylmYiA65+0xNgN2ZjB QgOrnpK3DjrXo7BZbIB9qsudsCpse0aLf/KDCHGcfCCx3WfC1POiu1FVK22LH5TXZu6ZbxjHpxt Ss8TSnjGi7K45UTZ1L4V2jirW6Hz4mgTSfrjW3CdtGvmjoATMKynyOMgpGvRGR9WExbFd1jlNa1 n4rtq6jKWcbfZHKQCMEHk3F/JnHa7zDk/ou++/nZH1862yjehzhww== X-Received: by 2002:a05:600c:1c96:b0:431:5632:448b with SMTP id 5b1f17b1804b1-434fff9849dmr2482245e9.25.1733747888831; Mon, 09 Dec 2024 04:38:08 -0800 (PST) X-Google-Smtp-Source: AGHT+IEzxrIt2hL84FuIM5l+V57mX/GA9hUrrhEw+bUfQlZXN7YqyIgAcSrIvzXh5BA7Vs54nPmEKg== X-Received: by 2002:a05:600c:1c96:b0:431:5632:448b with SMTP id 5b1f17b1804b1-434fff9849dmr2482005e9.25.1733747888422; Mon, 09 Dec 2024 04:38:08 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 20/26] rust: re-export C types from qemu-api submodules Date: Mon, 9 Dec 2024 13:37:11 +0100 Message-ID: <20241209123717.99077-21-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733748878474116600 Content-Type: text/plain; charset="utf-8" Long term we do not want device code to use "bindings" at all, so make it possible to get the relevant types from the other modules of qemu-api. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Zhao Liu <zhao1.liu@intel.com> --- rust/qemu-api/src/qdev.rs | 7 +++++-- rust/qemu-api/src/qom.rs | 10 ++++++---- rust/qemu-api/src/sysbus.rs | 3 ++- rust/qemu-api/src/vmstate.rs | 9 +++++---- rust/qemu-api/tests/tests.rs | 3 ++- 5 files changed, 20 insertions(+), 12 deletions(-) diff --git a/rust/qemu-api/src/qdev.rs b/rust/qemu-api/src/qdev.rs index 1228dabaaaf..96a4b1515da 100644 --- a/rust/qemu-api/src/qdev.rs +++ b/rust/qemu-api/src/qdev.rs @@ -6,10 +6,13 @@ =20 use std::ffi::CStr; =20 +pub use bindings::{DeviceClass, DeviceState, Property}; + use crate::{ - bindings::{self, DeviceClass, DeviceState, Error, ObjectClass, Propert= y, VMStateDescription}, + bindings::{self, Error}, prelude::*, - qom::ClassInitImpl, + qom::{ClassInitImpl, ObjectClass}, + vmstate::VMStateDescription, zeroable::Zeroable, }; =20 diff --git a/rust/qemu-api/src/qom.rs b/rust/qemu-api/src/qom.rs index 9b316e07efa..6e3923d8ed0 100644 --- a/rust/qemu-api/src/qom.rs +++ b/rust/qemu-api/src/qom.rs @@ -36,7 +36,9 @@ =20 use std::{ffi::CStr, os::raw::c_void}; =20 -use crate::bindings::{self, Object, ObjectClass, TypeInfo}; +pub use bindings::{Object, ObjectClass}; + +use crate::bindings::{self, TypeInfo}; =20 unsafe extern "C" fn rust_instance_init<T: ObjectImpl>(obj: *mut Object) { // SAFETY: obj is an instance of T, since rust_instance_init<T> @@ -161,8 +163,8 @@ pub trait ObjectImpl: ObjectType + ClassInitImpl<Self::= Class> { /// /// Each struct will implement this trait with `T` equal to each /// superclass. For example, a device should implement at least -/// `ClassInitImpl<`[`DeviceClass`](crate::bindings::DeviceClass)`>` and -/// `ClassInitImpl<`[`ObjectClass`](crate::bindings::ObjectClass)`>`. +/// `ClassInitImpl<`[`DeviceClass`](crate::qdev::DeviceClass)`>` and +/// `ClassInitImpl<`[`ObjectClass`]`>`. /// /// Fortunately, this is almost never necessary. Instead, the Rust /// implementation of methods will usually come from a trait like @@ -193,7 +195,7 @@ pub trait ClassInitImpl<T> { /// /// The virtual method implementations usually come from another /// trait, for example [`DeviceImpl`](crate::qdev::DeviceImpl) - /// when `T` is [`DeviceClass`](crate::bindings::DeviceClass). + /// when `T` is [`DeviceClass`](crate::qdev::DeviceClass). /// /// On entry, `klass`'s parent class is initialized, while the other f= ields /// are all zero; it is therefore assumed that all fields in `T` can be diff --git a/rust/qemu-api/src/sysbus.rs b/rust/qemu-api/src/sysbus.rs index fa69cadd7c1..a23562d7273 100644 --- a/rust/qemu-api/src/sysbus.rs +++ b/rust/qemu-api/src/sysbus.rs @@ -7,10 +7,11 @@ pub use bindings::{SysBusDevice, SysBusDeviceClass}; =20 use crate::{ - bindings::{self, DeviceClass}, + bindings, cell::bql_locked, irq::InterruptSource, prelude::*, + qdev::DeviceClass, qom::ClassInitImpl, }; =20 diff --git a/rust/qemu-api/src/vmstate.rs b/rust/qemu-api/src/vmstate.rs index bedcf1e8f39..25c68b703ea 100644 --- a/rust/qemu-api/src/vmstate.rs +++ b/rust/qemu-api/src/vmstate.rs @@ -10,6 +10,8 @@ //! [`vmstate_fields`](crate::vmstate_fields) are meant to be used when //! declaring a device model state struct. =20 +pub use crate::bindings::VMStateDescription; + #[doc(alias =3D "VMSTATE_UNUSED_BUFFER")] #[macro_export] macro_rules! vmstate_unused_buffer { @@ -328,7 +330,7 @@ macro_rules! vmstate_fields { } =20 /// A transparent wrapper type for the `subsections` field of -/// [`VMStateDescription`](crate::bindings::VMStateDescription). +/// [`VMStateDescription`]. /// /// This is necessary to be able to declare subsection descriptions as sta= tics, /// because the only way to implement `Sync` for a foreign type (and `*con= st` @@ -342,9 +344,8 @@ macro_rules! vmstate_fields { =20 unsafe impl Sync for VMStateSubsectionsWrapper {} =20 -/// Helper macro to declare a list of subsections -/// ([`VMStateDescription`](`crate::bindings::VMStateDescription`)) into a -/// static and return a pointer to the array of pointers it created. +/// Helper macro to declare a list of subsections ([`VMStateDescription`]) +/// into a static and return a pointer to the array of pointers it created. #[macro_export] macro_rules! vmstate_subsections { ($($subsection:expr),*$(,)*) =3D> {{ diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index fc57eb81290..68557fb85c7 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -8,8 +8,9 @@ bindings::*, c_str, declare_properties, define_property, prelude::*, - qdev::DeviceImpl, + qdev::{DeviceImpl, DeviceState, Property}, qom::ObjectImpl, + vmstate::VMStateDescription, zeroable::Zeroable, }; =20 --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733748376; cv=none; d=zohomail.com; s=zohoarc; b=D2aFUi6ECVtwz2umb4ePMcMNZSe98PCuYxnhcd3J41Ti2PjubqBqaQtYPxX9n47pK7LgfsQDFsk1xg7h4mFI71udKNYzkl5VIXK8F4eytBNIdMGkvhSioKrDHY12GBOk1FD6KT/PWgYrykGC+HoU0YZmTqKNiOCnL5U3Btze7d8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733748376; 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=mka10JX4kza0QaAC8JzE3v6aWvEpjz7koPP+g4YXhzE=; b=n1ADEZ2IvbmkbTypUJPDUVt3cQ/dyIzgleRTN9Fgw8PM/I6TxXmh0qm3NOoQhMDr9+N8ENcXIBeOcdhQM7+rI/PjN0mLbbCb6ZYe2jtr+MLLEnafF1C3N4Iz+myVx1aB2nwDfmL8o5M/1AKP8ekqc8ZRksLnVRhyhsOAfm78UrA= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733748376899808.3102519004703; Mon, 9 Dec 2024 04:46:16 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd6S-00089V-Op; Mon, 09 Dec 2024 07:43:12 -0500 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 <pbonzini@redhat.com>) id 1tKd1l-00046a-Hi for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:22 -0500 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 <pbonzini@redhat.com>) id 1tKd1j-0007YS-Lu for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:17 -0500 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-422-mzZ2WhFzPeC38bb16QUb2Q-1; Mon, 09 Dec 2024 07:38:13 -0500 Received: by mail-wr1-f71.google.com with SMTP id ffacd0b85a97d-386333ea577so759670f8f.1 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:38:13 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3863157fb80sm8858577f8f.19.2024.12.09.04.38.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:38:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747895; 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=mka10JX4kza0QaAC8JzE3v6aWvEpjz7koPP+g4YXhzE=; b=YUSbc07wLSbhs0L1cX0t0yZJBz9J6afuRpGAI76wK6IiqDxehpqNplPiNjlspAA5EHGTEY 2sC0OtusaWOEcTrfchaWkxveRvPzUCPXssTRXxKqr8D5O6gJpws+f27Bg47WlmW5ezfi02 yAgnbK6ftem2nCJ0eFh2n005ymGyeLw= X-MC-Unique: mzZ2WhFzPeC38bb16QUb2Q-1 X-Mimecast-MFC-AGG-ID: mzZ2WhFzPeC38bb16QUb2Q X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747892; x=1734352692; 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=mka10JX4kza0QaAC8JzE3v6aWvEpjz7koPP+g4YXhzE=; b=NfaZ1wLk+vK7MIUOiFgBK7Pu1mA/TzHmgIamILDzLqV4myRTAOF8GXxO/a+VxwV+F9 M13+ejEv269JnO6IKk3Yo9a6UKF6VeAkyEFXuw6XB/fZAsdgSD5FvPTf9HRjZ2DvaCmS Gvl+98W8/9/mRRDUqz3v89vg2cJg3cTZ/ro8rO0Db+UhQ3XoguiKYUfrmXvXxImDG/j8 DBFZCthCnW+zMeel45HkABD1/RYgII2qR0KEv/Qvm+l5qXbcqjtADd5MEY08ITUyTgSU E9OcUgHjzc8X+bFLntR2sdMo0a3nwVyk4Kn4XuUHK+Yxy5e6HLunKzDd3immehjYFuM1 CBeQ== X-Gm-Message-State: AOJu0YwwckCpVOV132g+pE8HJgz2QxpA2yidAg1L4lXCfxEnB28jPUZe BXE6nv3oNdbg/6cQ+4KC8CchIFMjKKLLGuYuavYfngBUFuGdU5mAuPBlfTt8YvYUVFS6VbJaMdc T29RS1aFCXKU2PTJ7a+4MvLRBbGmGGqxeCsZtGduB6nwjhOkBrpdtKBJzh13ADSkVIACnavxLCi fiECjDT76bgcd/9KRZ1eqamCcezMplo3wJt9ER X-Gm-Gg: ASbGncuOV0VqyBNHuM6fgHR4W8cdSaYtAxTzyHVEqX0OPXSk+/B4l07XVPy6jAZ8Lwn IcT6AoJqLYmVkjwqWqoYjZu3aZ2qnIJATWnb3PZ935PCo+lkxVHrSrsN//Wiqtpt2hJTMs7pRKa x/sT51XiU7OAo6zLDuQmwh5HmliV+8kGS8fVip0wMxt1qO+I4x24AcEZLWOMDyeUSJH+VWLeikY Rel/GrwS+ZKFgqFOe1EDw3dmqxnhbROxTMkleHkIc8mUfrm393WFQ== X-Received: by 2002:a5d:59a3:0:b0:386:4034:f9a0 with SMTP id ffacd0b85a97d-386453fbb7bmr127788f8f.52.1733747891660; Mon, 09 Dec 2024 04:38:11 -0800 (PST) X-Google-Smtp-Source: AGHT+IFOnitS1ndfRTSOAjmo4Aa07KZ1CsUCHy4hN4mqjX15w2pubCe4lwMeORYD14VyBTeSTiuEMg== X-Received: by 2002:a5d:59a3:0:b0:386:4034:f9a0 with SMTP id ffacd0b85a97d-386453fbb7bmr127766f8f.52.1733747891207; Mon, 09 Dec 2024 04:38:11 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 21/26] rust: tests: allow writing more than one test Date: Mon, 9 Dec 2024 13:37:12 +0100 Message-ID: <20241209123717.99077-22-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=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: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733748377958116600 Content-Type: text/plain; charset="utf-8" Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Zhao Liu <zhao1.liu@intel.com> --- rust/qemu-api/tests/tests.rs | 109 ++++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 48 deletions(-) diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index 68557fb85c7..18738a80008 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -2,7 +2,7 @@ // Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org> // SPDX-License-Identifier: GPL-2.0-or-later =20 -use std::ffi::CStr; +use std::{cell::Cell, ffi::CStr, sync::Mutex}; =20 use qemu_api::{ bindings::*, @@ -14,55 +14,68 @@ zeroable::Zeroable, }; =20 +// Test that macros can compile. +pub static VMSTATE: VMStateDescription =3D VMStateDescription { + name: c_str!("name").as_ptr(), + unmigratable: true, + ..Zeroable::ZERO +}; + +#[derive(qemu_api_macros::offsets)] +#[repr(C)] +#[derive(qemu_api_macros::Object)] +pub struct DummyState { + parent: DeviceState, + migrate_clock: bool, +} + +declare_properties! { + DUMMY_PROPERTIES, + define_property!( + c_str!("migrate-clk"), + DummyState, + migrate_clock, + unsafe { &qdev_prop_bool }, + bool + ), +} + +unsafe impl ObjectType for DummyState { + type Class =3D <DeviceState as ObjectType>::Class; + const TYPE_NAME: &'static CStr =3D c_str!("dummy"); +} + +impl ObjectImpl for DummyState { + type ParentType =3D DeviceState; + const ABSTRACT: bool =3D false; +} + +impl DeviceImpl for DummyState { + fn properties() -> &'static [Property] { + &DUMMY_PROPERTIES + } + fn vmsd() -> Option<&'static VMStateDescription> { + Some(&VMSTATE) + } +} + +fn init_qom() { + static ONCE: Mutex<Cell<bool>> =3D Mutex::new(Cell::new(false)); + + let g =3D ONCE.lock().unwrap(); + if !g.get() { + unsafe { + module_call_init(module_init_type::MODULE_INIT_QOM); + } + g.set(true); + } +} + #[test] -fn test_device_decl_macros() { - // Test that macros can compile. - pub static VMSTATE: VMStateDescription =3D VMStateDescription { - name: c_str!("name").as_ptr(), - unmigratable: true, - ..Zeroable::ZERO - }; - - #[derive(qemu_api_macros::offsets)] - #[repr(C)] - #[derive(qemu_api_macros::Object)] - pub struct DummyState { - pub _parent: DeviceState, - pub migrate_clock: bool, - } - - declare_properties! { - DUMMY_PROPERTIES, - define_property!( - c_str!("migrate-clk"), - DummyState, - migrate_clock, - unsafe { &qdev_prop_bool }, - bool - ), - } - - unsafe impl ObjectType for DummyState { - type Class =3D <DeviceState as ObjectType>::Class; - const TYPE_NAME: &'static CStr =3D c_str!("dummy"); - } - - impl ObjectImpl for DummyState { - type ParentType =3D DeviceState; - const ABSTRACT: bool =3D false; - } - - impl DeviceImpl for DummyState { - fn properties() -> &'static [Property] { - &DUMMY_PROPERTIES - } - fn vmsd() -> Option<&'static VMStateDescription> { - Some(&VMSTATE) - } - } - +/// Create and immediately drop an instance. +fn test_object_new() { + init_qom(); unsafe { - module_call_init(module_init_type::MODULE_INIT_QOM); object_unref(object_new(DummyState::TYPE_NAME.as_ptr()).cast()); } } --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733748790; cv=none; d=zohomail.com; s=zohoarc; b=C3ePsnqc2iKKIQ+JHPH6C16YhasC2TQsV0URt+GHg+9KFpNbzsBb/29Sf8TR2Z01AIn70tmo5YJOEjjQ5k2dg8dx4WKXZWI3TcOF91p9e/MnT/fZyuGBxHcfslouVCxrUyV7J/E4KIB4A+6gs8ECOOWhfXF28kM7IY7KoLFwi88= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733748790; 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=x23renJbAqH9SGoSoD8Jkh2+3+E9tn5by2w2whLGoz0=; b=bvXbzDxF8DFHkn4dPDZmb9u9wnQiPeZlSb0KlXmG0EMsfeETgN931gwazk+0TQ0Wn8kdw55VhddoGCyhbMFO3CUrGmRVq7T8BKuSyypLNl7zbmOD81i42T30QW6KUyzfrW5FcadnxyRfQWWl0pJhtu9wE1sG+iMWsD3r717NeNc= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733748790954964.5622650088586; Mon, 9 Dec 2024 04:53:10 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd4L-0006yy-Af; Mon, 09 Dec 2024 07:40:58 -0500 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 <pbonzini@redhat.com>) id 1tKd1q-0004AJ-Jt for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:25 -0500 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 <pbonzini@redhat.com>) id 1tKd1n-0007Yz-2l for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:21 -0500 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-175-YeIHS91vMgK7Nm7qRUUPxA-1; Mon, 09 Dec 2024 07:38:17 -0500 Received: by mail-wm1-f72.google.com with SMTP id 5b1f17b1804b1-434f7516bf2so4557095e9.1 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:38:16 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-434f95bd258sm33300425e9.14.2024.12.09.04.38.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:38:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747898; 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=x23renJbAqH9SGoSoD8Jkh2+3+E9tn5by2w2whLGoz0=; b=Lls16A1F/4MUz+S1STzd0UQlcCkKjvOqF8cVRYkXACRJP0jug2Day8/0MSj+oXJEgJkiOR pQ90tU6ritmgd0LGG7z2XxRLS6Y+W8GSDG0UPRnC1lBw8tapJ2E+1k9/nU2lTQ1VcDwo+P n5LFy4O8LG8oTD7tHyW44B/JflWUxkk= X-MC-Unique: YeIHS91vMgK7Nm7qRUUPxA-1 X-Mimecast-MFC-AGG-ID: YeIHS91vMgK7Nm7qRUUPxA X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747894; x=1734352694; 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=x23renJbAqH9SGoSoD8Jkh2+3+E9tn5by2w2whLGoz0=; b=uqlW992iibEvtGm1YQuvrtrjZoFqlRZXQgufvPRndqai2Rd5alHkZqt/s+IV3+OIZJ NkCKIrYLkt1VXnfjugIwXCOw3m/STcUKAvvtqCILJPnUQ4DJpXviHkaqPBoZXJ/jBcOs fivTxzC+MSIrnYvG1jlQv1qOCkh9N3yFzC3hJm8P/3RTU392YLs9dSb67vQJIf2JMwph 8uMaplMwuj5+5E9xgBSTbqbrWerVfcyfOCYdHL8YFD8a3mTeUEG+lTCoyMW4O5X//Wsg RZKNlblHJ0HvBJ1vg4L+P8RNfA0Ovm5hpkf8kh+R4gUxyeNIpfiqq5J8CDPInxQlAPs3 kcSA== X-Gm-Message-State: AOJu0Yzsn2VzgvkWHNrr4X4MvSWxOkzt2J7spC05XRoaLYlVlaR7Od4Y cULoqEBYgaOzjStDbXSg54KBHnR7+9Ji5TcC9hov/T+9Mg238IBzkPhuX027cxBtaVl7FT4hp0W GprWNCcKG3mAZWgYw/4/fRopV+D1NtU3l8+HuvUnsm+7auypWbflaowWwyBNU8fWizj4zex0Dd4 0JMysRfiayM9sMyVgYII60RyenqHzj4Tk1qA3x X-Gm-Gg: ASbGncs+JUzocwW/Xx02zqDZNMX+eHv4HagKm4PJtGPL975OYAYWE6ysswagvjAX2gd cRrhhV2O088PJMFWpmm/mKTfxZvpEISX3givmRzQ5mrJnyjxkSry3sXgW8bVOs1yQBH6A6Fwnq7 mBZ3CPGEazgV+FOkq9gTE/LtW0hCzECmOwxrmvXw4OmzYEim+76rvOhKlic7neezobRFSy5MIfi 1vgVnC+i+6bqh8fBXg6v28haAwzPGtxRFukNyFF7nQlFTgYBY0sQA== X-Received: by 2002:a05:600c:458a:b0:434:9d55:620 with SMTP id 5b1f17b1804b1-434dded7ac2mr89007385e9.11.1733747893990; Mon, 09 Dec 2024 04:38:13 -0800 (PST) X-Google-Smtp-Source: AGHT+IEkda1Tb5xVdepTs0aSk9wqzVzJiaCG/g5MT3vL7H6NC5XBEd++grhjTlSeVoyZdos/aSoLzw== X-Received: by 2002:a05:600c:458a:b0:434:9d55:620 with SMTP id 5b1f17b1804b1-434dded7ac2mr89007135e9.11.1733747893383; Mon, 09 Dec 2024 04:38:13 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 22/26] rust: qom: add casting functionality Date: Mon, 9 Dec 2024 13:37:13 +0100 Message-ID: <20241209123717.99077-23-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733748902473116600 Content-Type: text/plain; charset="utf-8" Add traits that let client cast typecast safely between object types. In particular, an upcast is compile-time guaranteed to succeed, and a YOLO C-style downcast must be marked as unsafe. The traits are based on an IsA<> trait that declares what is a subclass of what, which is an idea taken from glib-rs (https://docs.rs/glib/latest/glib/object/trait.IsA.html). The four primitives are also taken from there (https://docs.rs/glib/latest/glib/object/trait.Cast.html). However, the implementation of casting itself is a bit different and uses the Deref trait. This removes some pointer arithmetic from the pl011 device; it is also a prerequisite for the definition of methods, so that they can be invoked on all subclass structs. This will use the IsA<> trait to detect the structs that support the methods. glib also has a "monadic" casting trait which could be implemented on Option (as in https://docs.rs/glib/latest/glib/object/trait.CastNone.html) and perhaps even Result. For now I'm leaving it out, as the patch is already big enough and the benefit seems debatable. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Zhao Liu <zhao1.liu@intel.com> --- rust/Cargo.toml | 1 + rust/hw/char/pl011/src/device.rs | 12 +- rust/qemu-api/src/prelude.rs | 7 + rust/qemu-api/src/qdev.rs | 1 + rust/qemu-api/src/qom.rs | 279 ++++++++++++++++++++++++++++++- rust/qemu-api/src/sysbus.rs | 3 +- rust/qemu-api/tests/tests.rs | 70 +++++++- 7 files changed, 362 insertions(+), 11 deletions(-) diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 6ec19b67297..5b6b6ca4382 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -38,6 +38,7 @@ should_implement_trait =3D "deny" unused_self =3D "allow" =20 # default-allow lints +as_ptr_cast_mut =3D "deny" as_underscore =3D "deny" assertions_on_result_states =3D "deny" bool_to_int_with_if =3D "deny" diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index 3fed8b4ad25..e85d13c5a2b 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -106,6 +106,8 @@ pub struct PL011State { device_id: DeviceId, } =20 +qom_isa!(PL011State : SysBusDevice, DeviceState, Object); + unsafe impl ObjectType for PL011State { type Class =3D <SysBusDevice as ObjectType>::Class; const TYPE_NAME: &'static CStr =3D crate::TYPE_PL011; @@ -140,8 +142,6 @@ impl PL011State { unsafe fn init(&mut self) { const CLK_NAME: &CStr =3D c_str!("clk"); =20 - let sbd =3D unsafe { &mut *(addr_of_mut!(*self).cast::<SysBusDevic= e>()) }; - // SAFETY: // // self and self.iomem are guaranteed to be valid at this point si= nce callers @@ -155,15 +155,16 @@ unsafe fn init(&mut self) { Self::TYPE_NAME.as_ptr(), 0x1000, ); + + let sbd: &mut SysBusDevice =3D self.upcast_mut(); sysbus_init_mmio(sbd, addr_of_mut!(self.iomem)); } =20 for irq in self.interrupts.iter() { + let sbd: &SysBusDevice =3D self.upcast(); sbd.init_irq(irq); } =20 - let dev =3D addr_of_mut!(*self).cast::<DeviceState>(); - // SAFETY: // // self.clock is not initialized at this point; but since `NonNull= <_>` is Copy, @@ -172,6 +173,7 @@ unsafe fn init(&mut self) { // calls this function to initialize the fields; therefore no code= is // able to access an invalid self.clock value. unsafe { + let dev: &mut DeviceState =3D self.upcast_mut(); self.clock =3D NonNull::new(qdev_init_clock_in( dev, CLK_NAME.as_ptr(), @@ -632,6 +634,8 @@ unsafe fn init(&mut self) { } } =20 +qom_isa!(PL011Luminary : PL011State, SysBusDevice, DeviceState, Object); + unsafe impl ObjectType for PL011Luminary { type Class =3D <PL011State as ObjectType>::Class; const TYPE_NAME: &'static CStr =3D crate::TYPE_PL011_LUMINARY; diff --git a/rust/qemu-api/src/prelude.rs b/rust/qemu-api/src/prelude.rs index 5cc41f081f9..a0a71fcd6bc 100644 --- a/rust/qemu-api/src/prelude.rs +++ b/rust/qemu-api/src/prelude.rs @@ -7,4 +7,11 @@ pub use crate::cell::BqlCell; pub use crate::cell::BqlRefCell; =20 +pub use crate::qom::IsA; +pub use crate::qom::Object; +pub use crate::qom::ObjectCast; +pub use crate::qom::ObjectCastMut; +pub use crate::qom::ObjectDeref; pub use crate::qom::ObjectType; + +pub use crate::qom_isa; diff --git a/rust/qemu-api/src/qdev.rs b/rust/qemu-api/src/qdev.rs index 96a4b1515da..35efd210087 100644 --- a/rust/qemu-api/src/qdev.rs +++ b/rust/qemu-api/src/qdev.rs @@ -143,3 +143,4 @@ unsafe impl ObjectType for DeviceState { const TYPE_NAME: &'static CStr =3D unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_DEVICE= ) }; } +qom_isa!(DeviceState: Object); diff --git a/rust/qemu-api/src/qom.rs b/rust/qemu-api/src/qom.rs index 6e3923d8ed0..7115d85df6f 100644 --- a/rust/qemu-api/src/qom.rs +++ b/rust/qemu-api/src/qom.rs @@ -4,9 +4,16 @@ =20 //! Bindings to access QOM functionality from Rust. //! -//! This module provides automatic creation and registration of `TypeInfo` -//! for classes that are written in Rust, and mapping between Rust traits -//! and QOM vtables. +//! The QEMU Object Model (QOM) provides inheritance and dynamic typing fo= r QEMU +//! devices. This module makes QOM's features available in Rust through tw= o main +//! mechanisms: +//! +//! * Automatic creation and registration of `TypeInfo` for classes that a= re +//! written in Rust, as well as mapping between Rust traits and QOM vtab= les. +//! +//! * Type-safe casting between parent and child classes, through the [`Is= A`] +//! trait and methods such as [`upcast`](ObjectCast::upcast) and +//! [`downcast`](ObjectCast::downcast). //! //! # Structure of a class //! @@ -34,11 +41,57 @@ //! typically with wrappers that call into the //! [`DeviceImpl`](crate::qdev::DeviceImpl) implementations. =20 -use std::{ffi::CStr, os::raw::c_void}; +use std::{ + ffi::CStr, + ops::{Deref, DerefMut}, + os::raw::c_void, +}; =20 pub use bindings::{Object, ObjectClass}; =20 -use crate::bindings::{self, TypeInfo}; +use crate::bindings::{self, object_dynamic_cast, TypeInfo}; + +/// Marker trait: `Self` can be statically upcasted to `P` (i.e. `P` is a = direct +/// or indirect parent of `Self`). +/// +/// # Safety +/// +/// The struct `Self` must be `#[repr(C)]` and must begin, directly or +/// indirectly, with a field of type `P`. This ensures that invalid casts, +/// which rely on `IsA<>` for static checking, are rejected at compile tim= e. +pub unsafe trait IsA<P: ObjectType>: ObjectType {} + +// SAFETY: it is always safe to cast to your own type +unsafe impl<T: ObjectType> IsA<T> for T {} + +/// Macro to mark superclasses of QOM classes. This enables type-safe +/// up- and downcasting. +/// +/// # Safety +/// +/// This macro is a thin wrapper around the [`IsA`] trait and performs +/// no checking whatsoever of what is declared. It is the caller's +/// responsibility to have $struct begin, directly or indirectly, with +/// a field of type `$parent`. +#[macro_export] +macro_rules! qom_isa { + ($struct:ty : $($parent:ty),* ) =3D> { + $( + // SAFETY: it is the caller responsibility to have $parent as = the + // first field + unsafe impl $crate::qom::IsA<$parent> for $struct {} + + impl AsRef<$parent> for $struct { + fn as_ref(&self) -> &$parent { + // SAFETY: follows the same rules as for IsA<U>, which= is + // declared above. + let ptr: *const Self =3D self; + unsafe { &*ptr.cast::<$parent>() } + } + } + )* + }; +} =20 unsafe extern "C" fn rust_instance_init<T: ObjectImpl>(obj: *mut Object) { // SAFETY: obj is an instance of T, since rust_instance_init<T> @@ -94,8 +147,224 @@ pub unsafe trait ObjectType: Sized { /// The name of the type, which can be passed to `object_new()` to /// generate an instance of this type. const TYPE_NAME: &'static CStr; + + /// Return the receiver as an Object. This is always safe, even + /// if this type represents an interface. + fn as_object(&self) -> &Object { + unsafe { &*self.as_object_ptr() } + } + + /// Return the receiver as a const raw pointer to Object. + /// This is preferrable to `as_object_mut_ptr()` if a C + /// function only needs a `const Object *`. + fn as_object_ptr(&self) -> *const Object { + self.as_ptr().cast() + } + + /// Return the receiver as a mutable raw pointer to Object. + /// + /// # Safety + /// + /// This cast is always safe, but because the result is mutable + /// and the incoming reference is not, this should only be used + /// for calls to C functions, and only if needed. + unsafe fn as_object_mut_ptr(&self) -> *mut Object { + self.as_object_ptr() as *mut _ + } } =20 +/// This trait provides safe casting operations for QOM objects to raw poi= nters, +/// to be used for example for FFI. The trait can be applied to any kind of +/// reference or smart pointers, and enforces correctness through the [`Is= A`] +/// trait. +pub trait ObjectDeref: Deref +where + Self::Target: ObjectType, +{ + /// Convert to a const Rust pointer, to be used for example for FFI. + /// The target pointer type must be the type of `self` or a superclass + fn as_ptr<U: ObjectType>(&self) -> *const U + where + Self::Target: IsA<U>, + { + let ptr: *const Self::Target =3D self.deref(); + ptr.cast::<U>() + } + + /// Convert to a mutable Rust pointer, to be used for example for FFI. + /// The target pointer type must be the type of `self` or a superclass. + /// Used to implement interior mutability for objects. + /// + /// # Safety + /// + /// This method is unsafe because it overrides const-ness of `&self`. + /// Bindings to C APIs will use it a lot, but otherwise it should not + /// be necessary. + unsafe fn as_mut_ptr<U: ObjectType>(&self) -> *mut U + where + Self::Target: IsA<U>, + { + #[allow(clippy::as_ptr_cast_mut)] + { + self.as_ptr::<U>() as *mut _ + } + } +} + +/// Trait that adds extra functionality for `&T` where `T` is a QOM +/// object type. Allows conversion to/from C objects in generic code. +pub trait ObjectCast: ObjectDeref + Copy +where + Self::Target: ObjectType, +{ + /// Safely convert from a derived type to one of its parent types. + /// + /// This is always safe; the [`IsA`] trait provides static verification + /// trait that `Self` dereferences to `U` or a child of `U`. + fn upcast<'a, U: ObjectType>(self) -> &'a U + where + Self::Target: IsA<U>, + Self: 'a, + { + // SAFETY: soundness is declared via IsA<U>, which is an unsafe tr= ait + unsafe { self.unsafe_cast::<U>() } + } + + /// Attempt to convert to a derived type. + /// + /// Returns `None` if the object is not actually of type `U`. This is + /// verified at runtime by checking the object's type information. + fn downcast<'a, U: IsA<Self::Target>>(self) -> Option<&'a U> + where + Self: 'a, + { + self.dynamic_cast::<U>() + } + + /// Attempt to convert between any two types in the QOM hierarchy. + /// + /// Returns `None` if the object is not actually of type `U`. This is + /// verified at runtime by checking the object's type information. + fn dynamic_cast<'a, U: ObjectType>(self) -> Option<&'a U> + where + Self: 'a, + { + unsafe { + // SAFETY: upcasting to Object is always valid, and the + // return type is either NULL or the argument itself + let result: *const U =3D + object_dynamic_cast(self.as_object_mut_ptr(), U::TYPE_NAME= .as_ptr()).cast(); + + result.as_ref() + } + } + + /// Convert to any QOM type without verification. + /// + /// # Safety + /// + /// What safety? You need to know yourself that the cast is correct; o= nly + /// use when performance is paramount. It is still better than a raw + /// pointer `cast()`, which does not even check that you remain in the + /// realm of QOM `ObjectType`s. + /// + /// `unsafe_cast::<Object>()` is always safe. + unsafe fn unsafe_cast<'a, U: ObjectType>(self) -> &'a U + where + Self: 'a, + { + unsafe { &*(self.as_ptr::<Self::Target>().cast::<U>()) } + } +} + +impl<T: ObjectType> ObjectDeref for &T {} +impl<T: ObjectType> ObjectCast for &T {} + +/// Trait for mutable type casting operations in the QOM hierarchy. +/// +/// This trait provides the mutable counterparts to [`ObjectCast`]'s conve= rsion +/// functions. Unlike `ObjectCast`, this trait returns `Result` for fallib= le +/// conversions to preserve the original smart pointer if the cast fails. = This +/// is necessary because mutable references cannot be copied, so a failed = cast +/// must return ownership of the original reference. For example: +/// +/// ```ignore +/// let mut dev =3D get_device(); +/// // If this fails, we need the original `dev` back to try something else +/// match dev.dynamic_cast_mut::<FooDevice>() { +/// Ok(foodev) =3D> /* use foodev */, +/// Err(dev) =3D> /* still have ownership of dev */ +/// } +/// ``` +pub trait ObjectCastMut: Sized + ObjectDeref + DerefMut +where + Self::Target: ObjectType, +{ + /// Safely convert from a derived type to one of its parent types. + /// + /// This is always safe; the [`IsA`] trait provides static verification + /// that `Self` dereferences to `U` or a child of `U`. + fn upcast_mut<'a, U: ObjectType>(self) -> &'a mut U + where + Self::Target: IsA<U>, + Self: 'a, + { + // SAFETY: soundness is declared via IsA<U>, which is an unsafe tr= ait + unsafe { self.unsafe_cast_mut::<U>() } + } + + /// Attempt to convert to a derived type. + /// + /// Returns `Ok(..)` if the object is of type `U`, or `Err(self)` if t= he + /// object if the conversion failed. This is verified at runtime by + /// checking the object's type information. + fn downcast_mut<'a, U: IsA<Self::Target>>(self) -> Result<&'a mut U, S= elf> + where + Self: 'a, + { + self.dynamic_cast_mut::<U>() + } + + /// Attempt to convert between any two types in the QOM hierarchy. + /// + /// Returns `Ok(..)` if the object is of type `U`, or `Err(self)` if t= he + /// object if the conversion failed. This is verified at runtime by + /// checking the object's type information. + fn dynamic_cast_mut<'a, U: ObjectType>(self) -> Result<&'a mut U, Self> + where + Self: 'a, + { + unsafe { + // SAFETY: upcasting to Object is always valid, and the + // return type is either NULL or the argument itself + let result: *mut U =3D + object_dynamic_cast(self.as_object_mut_ptr(), U::TYPE_NAME= .as_ptr()).cast(); + + result.as_mut().ok_or(self) + } + } + + /// Convert to any QOM type without verification. + /// + /// # Safety + /// + /// What safety? You need to know yourself that the cast is correct; o= nly + /// use when performance is paramount. It is still better than a raw + /// pointer `cast()`, which does not even check that you remain in the + /// realm of QOM `ObjectType`s. + /// + /// `unsafe_cast::<Object>()` is always safe. + unsafe fn unsafe_cast_mut<'a, U: ObjectType>(self) -> &'a mut U + where + Self: 'a, + { + unsafe { &mut *self.as_mut_ptr::<Self::Target>().cast::<U>() } + } +} + +impl<T: ObjectType> ObjectDeref for &mut T {} +impl<T: ObjectType> ObjectCastMut for &mut T {} + /// Trait a type must implement to be registered with QEMU. pub trait ObjectImpl: ObjectType + ClassInitImpl<Self::Class> { /// The parent of the type. This should match the first field of diff --git a/rust/qemu-api/src/sysbus.rs b/rust/qemu-api/src/sysbus.rs index a23562d7273..8193734bde4 100644 --- a/rust/qemu-api/src/sysbus.rs +++ b/rust/qemu-api/src/sysbus.rs @@ -11,7 +11,7 @@ cell::bql_locked, irq::InterruptSource, prelude::*, - qdev::DeviceClass, + qdev::{DeviceClass, DeviceState}, qom::ClassInitImpl, }; =20 @@ -20,6 +20,7 @@ unsafe impl ObjectType for SysBusDevice { const TYPE_NAME: &'static CStr =3D unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_SYS_BU= S_DEVICE) }; } +qom_isa!(SysBusDevice: DeviceState, Object); =20 // TODO: add SysBusDeviceImpl impl<T> ClassInitImpl<SysBusDeviceClass> for T diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index 18738a80008..549e9699c26 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -2,7 +2,13 @@ // Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org> // SPDX-License-Identifier: GPL-2.0-or-later =20 -use std::{cell::Cell, ffi::CStr, sync::Mutex}; +use std::{ + cell::Cell, + ffi::CStr, + os::raw::c_void, + ptr::{addr_of, addr_of_mut}, + sync::Mutex, +}; =20 use qemu_api::{ bindings::*, @@ -29,6 +35,8 @@ pub struct DummyState { migrate_clock: bool, } =20 +qom_isa!(DummyState: Object, DeviceState); + declare_properties! { DUMMY_PROPERTIES, define_property!( @@ -79,3 +87,63 @@ fn test_object_new() { object_unref(object_new(DummyState::TYPE_NAME.as_ptr()).cast()); } } + +// a note on all "cast" tests: usually, especially for downcasts the desir= ed +// class would be placed on the right, for example: +// +// let sbd_ref =3D p.dynamic_cast::<SysBusDevice>(); +// +// Here I am doing the opposite to check that the resulting type is correc= t. + +#[test] +#[allow(clippy::shadow_unrelated)] +/// Test casts on shared references. +fn test_cast() { + init_qom(); + let p: *mut DummyState =3D unsafe { object_new(DummyState::TYPE_NAME.a= s_ptr()).cast() }; + + let p_ref: &DummyState =3D unsafe { &*p }; + let obj_ref: &Object =3D p_ref.upcast(); + assert_eq!(addr_of!(*obj_ref), p.cast()); + + let sbd_ref: Option<&SysBusDevice> =3D obj_ref.dynamic_cast(); + assert!(sbd_ref.is_none()); + + let dev_ref: Option<&DeviceState> =3D obj_ref.downcast(); + assert_eq!(addr_of!(*dev_ref.unwrap()), p.cast()); + + // SAFETY: the cast is wrong, but the value is only used for comparison + unsafe { + let sbd_ref: &SysBusDevice =3D obj_ref.unsafe_cast(); + assert_eq!(addr_of!(*sbd_ref), p.cast()); + + object_unref(p_ref.as_object_mut_ptr().cast::<c_void>()); + } +} + +#[test] +#[allow(clippy::shadow_unrelated)] +/// Test casts on mutable references. +fn test_cast_mut() { + init_qom(); + let p: *mut DummyState =3D unsafe { object_new(DummyState::TYPE_NAME.a= s_ptr()).cast() }; + + let p_ref: &mut DummyState =3D unsafe { &mut *p }; + let obj_ref: &mut Object =3D p_ref.upcast_mut(); + assert_eq!(addr_of_mut!(*obj_ref), p.cast()); + + let sbd_ref: Result<&mut SysBusDevice, &mut Object> =3D obj_ref.dynami= c_cast_mut(); + let obj_ref =3D sbd_ref.unwrap_err(); + + let dev_ref: Result<&mut DeviceState, &mut Object> =3D obj_ref.downcas= t_mut(); + let dev_ref =3D dev_ref.unwrap(); + assert_eq!(addr_of_mut!(*dev_ref), p.cast()); + + // SAFETY: the cast is wrong, but the value is only used for comparison + unsafe { + let sbd_ref: &mut SysBusDevice =3D obj_ref.unsafe_cast_mut(); + assert_eq!(addr_of_mut!(*sbd_ref), p.cast()); + + object_unref(p_ref.as_object_mut_ptr().cast::<c_void>()); + } +} --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733748274; cv=none; d=zohomail.com; s=zohoarc; b=UxB+WCOq6Zrn9eSJQczR5/DPqZGWyJml0m19hixoCAIt60yQUb8eQaoiwHvOu1dKjgJDah9BrK3C9ghaCBGZyyXzsGcu8m+yJ8YRAXxfF23E82DCmE/zO32ZsEHBAMgb4uYadf4cwxICOei8yKBJUP3ew7NUnKKoGc4GX6anWdM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733748274; 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=8uEcPFIxXxKd/mahbXkvWTwydRcIWtDLPmh0PhjQLUk=; b=mRV5lQqF9Pvogrm4zgfhfH/UfMJ3z0EYHlFeqPEGC9GfRcfXAUFBeIOwGpAjHr5MZh0ZF+iJ2sirUwi41kNjspozWZQBx6O2KFJ1BehHaxUdBrZ7WAf/bFOhRZDs/2CAjeHsM9pbKXPNyYnWAJeiHsg0bkBX/KGaiY9x0g/TY9o= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733748272997322.5062997530689; Mon, 9 Dec 2024 04:44:32 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd56-0007eo-LQ; Mon, 09 Dec 2024 07:41:55 -0500 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 <pbonzini@redhat.com>) id 1tKd1r-0004AV-Mz for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:25 -0500 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 <pbonzini@redhat.com>) id 1tKd1p-0007ZL-QT for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:23 -0500 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-665-nXVJ5KmGOriX5qyrtsg14A-1; Mon, 09 Dec 2024 07:38:18 -0500 Received: by mail-wr1-f71.google.com with SMTP id ffacd0b85a97d-385dcae001fso1568752f8f.1 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:38:18 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3862de365f0sm9885129f8f.3.2024.12.09.04.38.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:38:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747901; 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=8uEcPFIxXxKd/mahbXkvWTwydRcIWtDLPmh0PhjQLUk=; b=A73kbRsHv7SiU+Iw7zzFDXNrxMLfP36fKOAIKeJUOdNgHxrs58dW/yF0p0P9t5F4me4pen mUF6U8+9mYLGYnbMByDGGOatynVPzloU35boR0zdgw96LxFIkyZoqN+WLEamtFRF/GB5Ls daIECAQVRMTxdDm1ejZtl8pcDaIbHnE= X-MC-Unique: nXVJ5KmGOriX5qyrtsg14A-1 X-Mimecast-MFC-AGG-ID: nXVJ5KmGOriX5qyrtsg14A X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747895; x=1734352695; 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=8uEcPFIxXxKd/mahbXkvWTwydRcIWtDLPmh0PhjQLUk=; b=YHbhY8WTeVi/F3mKkGezT/qLWeyn6lpEpImOJ7qVfJtmnHQKyjQ8CF66xmwGqy7esz oNCSD7jgnQdmwWP9/Lwnd3Qz+2kn70WKEXAZqFIDZYNG7hRdEqh+nInzcX/7Ku9TLBUA 3TkagcNP/k9eYxPxpdfDi1mZ5zakHimIfdIRvxDhR9IV0X/UFTpWSiIfaEOJnH9RdvSS Ai2EvcxxGHlXL1/w8G/SXRG80Gk6cbbb4UWeoSsOLpgf/gfq+Lq5zkmLmM5bgK6esQIQ pUja+6jxT8SK/KMn8gZdi/I6QsMkyTkOlSGI/ZwwG7sm0cPv1yVovmKL8RqeQEHOWwQD OsZQ== X-Gm-Message-State: AOJu0Yw87ge28BHHff/6H5EOLwohuPv99xLB4aoCqJd+9Me6bcQjo+Nt g63Uxqmj/PLGPWAhW8FqbuZUwL1/HhMhcGptIPa3pujojOHuIKhqFeRUlvrdhuGllrO0+urUIo4 cNBUkQVaZmh7pm7Z3fl0RoHAlsIOheugdGblvAwZd/u0oCa+YixLHsD/Fv5Djf1xZ7EcbmqOeMi dXkrXBWvo7GHWIQDW5nOxihxvjjpKpzi/6bmE1 X-Gm-Gg: ASbGnctw/F6GnYUVAfVR3Qy2r/KNNW3jNzrw6aAmpmPUG9oh3GoibgFbPODa/Xdk0g0 9IdS18aCjUCPxyDtYKq7SVR2UDwZC5R/TzTjA7nvAws8tbC8PmQaTp8aC0KOTew8I/XtKYI/PR9 JejDsaUUu9VLuN33m5Ru2Y6yh3qiH7EijAlVHnFvI3HD4AUPa4lW+F4B1ZuzBR0ulVePoivjP51 Kqt5wu9EN7UllBvruB7ee47kQ8FZ4IRpu7an8IoeNxRZs4INIKGDg== X-Received: by 2002:a05:6000:184d:b0:385:ef39:6cd5 with SMTP id ffacd0b85a97d-3862b33ef3dmr8472042f8f.1.1733747895442; Mon, 09 Dec 2024 04:38:15 -0800 (PST) X-Google-Smtp-Source: AGHT+IEWJMYdNT8YTYcEVF0k48QxoZc6Rdq22mNcPglVw95b1mKCZ+fBrZ9tkmS/t/2k80Wvfqg3Dg== X-Received: by 2002:a05:6000:184d:b0:385:ef39:6cd5 with SMTP id ffacd0b85a97d-3862b33ef3dmr8472015f8f.1.1733747894960; Mon, 09 Dec 2024 04:38:14 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 23/26] rust: qom: add initial subset of methods on Object Date: Mon, 9 Dec 2024 13:37:14 +0100 Message-ID: <20241209123717.99077-24-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=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: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733748279615116600 Content-Type: text/plain; charset="utf-8" Add an example of implementing instance methods and converting the result back to a Rust type. In this case the returned types are a string (actually a Cow<str>; but that's transparent as long as it derefs to &str) and a QOM class. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Zhao Liu <zhao1.liu@intel.com> --- rust/qemu-api/src/prelude.rs | 1 + rust/qemu-api/src/qom.rs | 56 ++++++++++++++++++++++++++++++++++-- rust/qemu-api/tests/tests.rs | 12 ++++++++ 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/rust/qemu-api/src/prelude.rs b/rust/qemu-api/src/prelude.rs index a0a71fcd6bc..6f32deeb2ed 100644 --- a/rust/qemu-api/src/prelude.rs +++ b/rust/qemu-api/src/prelude.rs @@ -12,6 +12,7 @@ pub use crate::qom::ObjectCast; pub use crate::qom::ObjectCastMut; pub use crate::qom::ObjectDeref; +pub use crate::qom::ObjectMethods; pub use crate::qom::ObjectType; =20 pub use crate::qom_isa; diff --git a/rust/qemu-api/src/qom.rs b/rust/qemu-api/src/qom.rs index 7115d85df6f..d7475b8ed6a 100644 --- a/rust/qemu-api/src/qom.rs +++ b/rust/qemu-api/src/qom.rs @@ -5,8 +5,8 @@ //! Bindings to access QOM functionality from Rust. //! //! The QEMU Object Model (QOM) provides inheritance and dynamic typing fo= r QEMU -//! devices. This module makes QOM's features available in Rust through tw= o main -//! mechanisms: +//! devices. This module makes QOM's features available in Rust through th= ree +//! main mechanisms: //! //! * Automatic creation and registration of `TypeInfo` for classes that a= re //! written in Rust, as well as mapping between Rust traits and QOM vtab= les. @@ -15,6 +15,11 @@ //! trait and methods such as [`upcast`](ObjectCast::upcast) and //! [`downcast`](ObjectCast::downcast). //! +//! * Automatic delegation of parent class methods to child classes. When a +//! trait uses [`IsA`] as a bound, its contents become available to all = child +//! classes through blanket implementations. This works both for class m= ethods +//! and for instance methods accessed through references or smart pointe= rs. +//! //! # Structure of a class //! //! A concrete class only needs a struct holding instance state. The struc= t must @@ -40,6 +45,16 @@ //! `ClassInitImpl<DeviceClass>`. This fills the vtable in the class str= uct, //! typically with wrappers that call into the //! [`DeviceImpl`](crate::qdev::DeviceImpl) implementations. +//! +//! * a trait for instance methods, for example `DeviceMethods`. This trai= t is +//! automatically implemented for any reference or smart pointer to a de= vice +//! instance. It calls into the vtable provides access across all subcl= asses +//! to methods defined for the class. +//! +//! * optionally, a trait for class methods, for example `DeviceClassMetho= ds`. +//! This provides access to class-wide functionality that doesn't depend= on +//! instance data. Like instance methods, these are automatically inheri= ted by +//! child classes. =20 use std::{ ffi::CStr, @@ -49,7 +64,7 @@ =20 pub use bindings::{Object, ObjectClass}; =20 -use crate::bindings::{self, object_dynamic_cast, TypeInfo}; +use crate::bindings::{self, object_dynamic_cast, object_get_class, object_= get_typename, TypeInfo}; =20 /// Marker trait: `Self` can be statically upcasted to `P` (i.e. `P` is a = direct /// or indirect parent of `Self`). @@ -504,3 +519,38 @@ unsafe impl ObjectType for Object { const TYPE_NAME: &'static CStr =3D unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_OBJECT= ) }; } + +/// Trait for methods exposed by the Object class. The methods can be +/// called on all objects that have the trait `IsA<Object>`. +/// +/// The trait should only be used through the blanket implementation, +/// which guarantees safety via `IsA` +pub trait ObjectMethods: ObjectDeref +where + Self::Target: IsA<Object>, +{ + /// Return the name of the type of `self` + fn typename(&self) -> std::borrow::Cow<'_, str> { + let obj =3D self.upcast::<Object>(); + // SAFETY: safety of this is the requirement for implementing IsA + // The result of the C API has static lifetime + unsafe { + let p =3D object_get_typename(obj.as_mut_ptr()); + CStr::from_ptr(p).to_string_lossy() + } + } + + fn get_class(&self) -> &'static <Self::Target as ObjectType>::Class { + let obj =3D self.upcast::<Object>(); + + // SAFETY: all objects can call object_get_class; the actual class + // type is guaranteed by the implementation of `ObjectType` and + // `ObjectImpl`. + let klass: &'static <Self::Target as ObjectType>::Class =3D + unsafe { &*object_get_class(obj.as_mut_ptr()).cast() }; + + klass + } +} + +impl<R: ObjectDeref> ObjectMethods for R where R::Target: IsA<Object> {} diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index 549e9699c26..4c766c7f808 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -88,6 +88,18 @@ fn test_object_new() { } } =20 +#[test] +/// Try invoking a method on an object. +fn test_typename() { + init_qom(); + let p: *mut DummyState =3D unsafe { object_new(DummyState::TYPE_NAME.a= s_ptr()).cast() }; + let p_ref: &DummyState =3D unsafe { &*p }; + assert_eq!(p_ref.typename(), "dummy"); + unsafe { + object_unref(p_ref.as_object_mut_ptr().cast::<c_void>()); + } +} + // a note on all "cast" tests: usually, especially for downcasts the desir= ed // class would be placed on the right, for example: // --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733748714; cv=none; d=zohomail.com; s=zohoarc; b=QP6wZtzyzLFJw9r+nhxZeXCsp208fzaa1/dkLAY4YVWqqNVRoOJyhJDq+XGX4j+6O8WjJkJ4SJzSFc3SpbEOwTYQDpkDvLzlGyC3J3vTrwhdB2baEaVoKrJW8ogSRUyqyAJqm0sWilJYRnSgEUfwr9Romm/TGpC14OSgVDxSuVg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733748714; 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=YJRarGtTvkM8QsI1PbQS6ZxbhzzviSf81sTcl05pEiA=; b=bKDvK8NnBneayKfqHxXzhqIlxIW8eVsV6w1joGJikaeJ92W+k4nvsM93LYlf0rFr5tB6hGNRoldGOoqPAWr2QkW4LenV8lypro0C3KwC50KvgSaDE9318vXhuLFg2JwsnvgKbxBs2aMk8du3/qTghOPVYHmxWxzKg2lx5LRmWaw= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733748714415832.8624144137964; Mon, 9 Dec 2024 04:51:54 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd76-0000Fz-2Z; Mon, 09 Dec 2024 07:43:51 -0500 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 <pbonzini@redhat.com>) id 1tKd1x-0004L3-VQ for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:31 -0500 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 <pbonzini@redhat.com>) id 1tKd1r-0007Zg-4Y for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:29 -0500 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-222-uh_HQE4pNkK3DWHp8eQzuw-1; Mon, 09 Dec 2024 07:38:21 -0500 Received: by mail-wr1-f70.google.com with SMTP id ffacd0b85a97d-3862be3bfc9so1607157f8f.3 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:38:21 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-386219098d3sm13322459f8f.70.2024.12.09.04.38.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:38:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747902; 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=YJRarGtTvkM8QsI1PbQS6ZxbhzzviSf81sTcl05pEiA=; b=g2sYVBiKk/KbJRE4Fppf+H+MklhDLBC8wnccLnWQ/h89XBejz+LBKVffwGHnjS4a+ouP5h 7ymcuGAE84kQQX+Qe/7pk3tJn5l15Mbb3y6f2gzJ9SMUODtbujDzZwGtaCqlgp1ay5diKx NSgIARGHyDT+fcoHrzVzGLdQgAjQ1hI= X-MC-Unique: uh_HQE4pNkK3DWHp8eQzuw-1 X-Mimecast-MFC-AGG-ID: uh_HQE4pNkK3DWHp8eQzuw X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747899; x=1734352699; 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=YJRarGtTvkM8QsI1PbQS6ZxbhzzviSf81sTcl05pEiA=; b=k/h/Qxja/j1IRV7fAjguqW68Jt4KYpxaKyWW3hY5nIE3hVDaBk2ITvYP2M7ttpt0LZ +j7NmPU1dB2s0DiBDR3Dx4m9srREiAJ6rgLDxCflHSilZgLTY9r0fnwLt8O0Yvi8fMSs zDuUlxhE9t6GJjFLKJWZX8VqZy1nVwDBHND4zb1YMckACnEQNhy032c/iwuSyBx5qKDa 2iXX8M7rL5koynIURILnDKGCDX7Pa2vp2EdL3U909SjK8uevbbhymxeam9nQ6iHZipBR WDssZHQgtvTwqBQpDiggOGcOQix3yCQ+SeQVn4FdVUnxCIylx1cUZePBRs0X7YjehkSN QUnw== X-Gm-Message-State: AOJu0Yw8ogDWEgjt4H9E+z6FeTSWviOZ/RNw102+rpZuIXCL5RrJ022G ZrPXz6olpH3Fj+viPelIg3gl+CZSshRb1vxUG4H+Now2gb10jcxQxApQfDuNcdTLE1DqlsTK4WQ 7XQJNvgIr7QqOKS5LmtUGhB36B2cJDNdNExdEhKS1L+pw8cd13wthHhr3IkQpCspBCvpyyOKLeR 6LBvwL7il2uSYHzhJhhiLpfPyC7rGbCDCaLhX3 X-Gm-Gg: ASbGnct9PdUe2QCoIa/A9czb9u+1HukdiB3HJ5HZfCrQ95qX4nyLE7nYL+ttLelimt3 B3ZiXyPpos2FZF9jEIqll8nOi4iDdAxHwjo2fLs5/lUWpOjNav28ppukMt1saf1rGHKHdslHfKm LV3pY4DggGFx20oTY8WMuL4CNMkMTf2dHVTO2+8njezLsiu5PnETDeDxHfy3CQKDWxyibBrsxLU 56DI98gwFNaJDxWZh3BiI1fB31zs3O+FsVHaxrgWA3u9iDY1rEl2g== X-Received: by 2002:a5d:5f8f:0:b0:385:de67:228d with SMTP id ffacd0b85a97d-3862b36ccf8mr7497016f8f.21.1733747899274; Mon, 09 Dec 2024 04:38:19 -0800 (PST) X-Google-Smtp-Source: AGHT+IHAabb6hI6BtQ2yeCXBE0/4aE5JAUvqsTI5unR0FhR44d+JwapLUBECB3/0yAJ2JG752BWjCw== X-Received: by 2002:a5d:5f8f:0:b0:385:de67:228d with SMTP id ffacd0b85a97d-3862b36ccf8mr7497006f8f.21.1733747898823; Mon, 09 Dec 2024 04:38:18 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 24/26] rust: qom: move device_id to PL011 class side Date: Mon, 9 Dec 2024 13:37:15 +0100 Message-ID: <20241209123717.99077-25-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=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: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733748882393116600 Content-Type: text/plain; charset="utf-8" There is no need to monkeypatch DeviceId::Luminary into the already-initial= ized PL011State. Instead, now that we can define a class hierarchy, we can defi= ne PL011Class and make device_id a field in there. There is also no need anymore to have "Arm" as zero, so change DeviceId int= o a wrapper for the array; all it does is provide an Index<hwaddr> implementati= on because arrays can only be indexed by usize. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Zhao Liu <zhao1.liu@intel.com> --- rust/hw/char/pl011/src/device.rs | 59 +++++++++++++++----------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index e85d13c5a2b..41220c99a83 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -5,7 +5,7 @@ use core::ptr::{addr_of_mut, NonNull}; use std::{ ffi::CStr, - os::raw::{c_int, c_uchar, c_uint, c_void}, + os::raw::{c_int, c_uint, c_void}, }; =20 use qemu_api::{ @@ -14,7 +14,7 @@ irq::InterruptSource, prelude::*, qdev::DeviceImpl, - qom::ObjectImpl, + qom::{ClassInitImpl, ObjectImpl}, }; =20 use crate::{ @@ -35,27 +35,20 @@ /// QEMU sourced constant. pub const PL011_FIFO_DEPTH: usize =3D 16_usize; =20 -#[derive(Clone, Copy, Debug)] -enum DeviceId { - #[allow(dead_code)] - Arm =3D 0, - Luminary, -} +#[derive(Clone, Copy)] +struct DeviceId(&'static [u8; 8]); =20 impl std::ops::Index<hwaddr> for DeviceId { - type Output =3D c_uchar; + type Output =3D u8; =20 fn index(&self, idx: hwaddr) -> &Self::Output { - match self { - Self::Arm =3D> &Self::PL011_ID_ARM[idx as usize], - Self::Luminary =3D> &Self::PL011_ID_LUMINARY[idx as usize], - } + &self.0[idx as usize] } } =20 impl DeviceId { - const PL011_ID_ARM: [c_uchar; 8] =3D [0x11, 0x10, 0x14, 0x00, 0x0d, 0x= f0, 0x05, 0xb1]; - const PL011_ID_LUMINARY: [c_uchar; 8] =3D [0x11, 0x00, 0x18, 0x01, 0x0= d, 0xf0, 0x05, 0xb1]; + const ARM: Self =3D Self(&[0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0= xb1]); + const LUMINARY: Self =3D Self(&[0x11, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x= 05, 0xb1]); } =20 #[repr(C)] @@ -102,17 +95,28 @@ pub struct PL011State { pub clock: NonNull<Clock>, #[doc(alias =3D "migrate_clk")] pub migrate_clock: bool, - /// The byte string that identifies the device. - device_id: DeviceId, } =20 qom_isa!(PL011State : SysBusDevice, DeviceState, Object); =20 +pub struct PL011Class { + parent_class: <SysBusDevice as ObjectType>::Class, + /// The byte string that identifies the device. + device_id: DeviceId, +} + unsafe impl ObjectType for PL011State { - type Class =3D <SysBusDevice as ObjectType>::Class; + type Class =3D PL011Class; const TYPE_NAME: &'static CStr =3D crate::TYPE_PL011; } =20 +impl ClassInitImpl<PL011Class> for PL011State { + fn class_init(klass: &mut PL011Class) { + klass.device_id =3D DeviceId::ARM; + <Self as ClassInitImpl<SysBusDeviceClass>>::class_init(&mut klass.= parent_class); + } +} + impl ObjectImpl for PL011State { type ParentType =3D SysBusDevice; =20 @@ -190,7 +194,8 @@ pub fn read(&mut self, offset: hwaddr, _size: c_uint) -= > std::ops::ControlFlow<u =20 std::ops::ControlFlow::Break(match RegisterOffset::try_from(offset= ) { Err(v) if (0x3f8..0x400).contains(&(v >> 2)) =3D> { - u64::from(self.device_id[(offset - 0xfe0) >> 2]) + let device_id =3D self.get_class().device_id; + u64::from(device_id[(offset - 0xfe0) >> 2]) } Err(_) =3D> { // qemu_log_mask(LOG_GUEST_ERROR, "pl011_read: Bad offset = 0x%x\n", (int)offset); @@ -621,16 +626,10 @@ pub struct PL011Luminary { parent_obj: PL011State, } =20 -impl PL011Luminary { - /// Initializes a pre-allocated, unitialized instance of `PL011Luminar= y`. - /// - /// # Safety - /// - /// We expect the FFI user of this function to pass a valid pointer, t= hat - /// has the same size as [`PL011Luminary`]. We also expect the device = is - /// readable/writeable from one thread at any time. - unsafe fn init(&mut self) { - self.parent_obj.device_id =3D DeviceId::Luminary; +impl ClassInitImpl<PL011Class> for PL011Luminary { + fn class_init(klass: &mut PL011Class) { + klass.device_id =3D DeviceId::LUMINARY; + <Self as ClassInitImpl<SysBusDeviceClass>>::class_init(&mut klass.= parent_class); } } =20 @@ -643,8 +642,6 @@ unsafe impl ObjectType for PL011Luminary { =20 impl ObjectImpl for PL011Luminary { type ParentType =3D PL011State; - - const INSTANCE_INIT: Option<unsafe fn(&mut Self)> =3D Some(Self::init); } =20 impl DeviceImpl for PL011Luminary {} --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733748213; cv=none; d=zohomail.com; s=zohoarc; b=KSCh/8jCvA3e5uF//QQ4eoaUqOmPtDykXd26YTwak0JBw9+jSA2oXETKnhiDNqiv7sgjuZD6OYj3yb4klOOVFZyA4vxxYm8UGQiDPVH4OzJ+uaO8+NoGMxeiT0CnvRKVHfQ0lYjjYzhfRqyLfQUGvrt/VTJKUMrJ/z9MNvA7lCA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733748213; 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=8FLRIc2gzS7c4NuJ1tEpqw/oXvphOkODjv2WDRCVJI0=; b=HS9vj0jHTaVTNLc1WBjqO5KVKzP/bMfz7Mb4Kdsw6IxkkzzTNB/8eCDIas9mlfMBV3IgvajaFQHxX+AhvStUKCe67N5K0lRS9V5TmoP3VOdZP8+AztaiKBFTeyy43Krh7jQuTItJi6qLKODj0ACOcemkUkh+4v8r1D4Pjho7kuA= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733748213151910.6371476830772; Mon, 9 Dec 2024 04:43:33 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd5o-0007rc-Ix; Mon, 09 Dec 2024 07:42:34 -0500 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 <pbonzini@redhat.com>) id 1tKd20-0004So-8Z for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:33 -0500 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 <pbonzini@redhat.com>) id 1tKd1u-0007Zw-G2 for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:31 -0500 Received: from mail-wr1-f72.google.com (mail-wr1-f72.google.com [209.85.221.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-91-FbbOFKYUOfKobCULKlwHGA-1; Mon, 09 Dec 2024 07:38:22 -0500 Received: by mail-wr1-f72.google.com with SMTP id ffacd0b85a97d-385e1fd40acso2322266f8f.3 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:38:22 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3861ecf3efasm12925978f8f.17.2024.12.09.04.38.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:38:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747904; 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=8FLRIc2gzS7c4NuJ1tEpqw/oXvphOkODjv2WDRCVJI0=; b=do4Q4GXetDa9nS07x644wkgAawuWmJzN6wxIdMV4H3GW/2cAslA9+pkh+dISD532LmQlwq hmTAZr0QpIsLk3IAWP+QCo10NyaRyw880d33+ZRhFP1duZEEJ54oi9qbrLzbdWHsdkfdf6 dpw322i//u8OlukLb4C2RIozyuA9igc= X-MC-Unique: FbbOFKYUOfKobCULKlwHGA-1 X-Mimecast-MFC-AGG-ID: FbbOFKYUOfKobCULKlwHGA X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747901; x=1734352701; 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=8FLRIc2gzS7c4NuJ1tEpqw/oXvphOkODjv2WDRCVJI0=; b=c4ojNBdoD4kbjxkrRZ3hMtxSwKgMVyKOhn/Ew6D9yWUiKFa+aXm0YuatfxUC9XsX9i LCw6R9EQKH36xY1fArcIlxJRB9OqRWsfaYxdNgMjSAPsgXVr+lL95pTNrj6zz/e49ANN AXst5T+krzuVltPv+eZkFK8pKca9I6k+tMf4t8Rwo7UZQyKim6SOLvZfw2Kqhvo0xyTG PFe7Kr8FWAqegCR0ATvncobgTijFdlLwPjG8pqWFc1xZ2VDu5APD/W6xy6Z/QXpfYBhf wD+FVHrEfEGBKhupGUcvUch+n8b2mPjVKlVhYYNOyNNUYhLv3Tso5K02cjIGJZwe9Omc A4Nw== X-Gm-Message-State: AOJu0YwmvBiXecgYG/KQOi+n9OUrwPr3biTXCAzVkg34yFEJGDhb811c Bakgh/XRvxp2h5r3uIMbq7BAgPTpXKfJZ/26AMTTv9BJozeCn9SWDim25GD/zcJ5P2PikTJmRHa jb4T0EvZmScrZNXADz7fnXdInfTCtFXc2Mzr7D3I0UfT7WfcFoUmVQAQXEcBgIWomYofYPi7Zs2 In/XpRaip234sn8qrNwcFJvweD1FttEbc700tE X-Gm-Gg: ASbGncskCoobJtfLi27bQZ0oAmac8P20LXggyG7Md6tignn+OfzaEUf4BJSqWVAURLu hNyXgN9Abg/j28VbGipJTioUeOg+N8U7kgWO3PpYWKgkoEFouVb1tzvHzENvHxTX4STNy26kwb0 eK35YuYGHK0kFZslyWkBMWSxpKHvI+WftuWvWifAMmywNmAN551nQwJKQTokDmuvINUIs60WYZM 97NS+fVnpKkxsiVclN3xIbEgraoKYCWw5qjgf9snKntPt7PCqaM6A== X-Received: by 2002:a05:6000:1fa5:b0:385:f00a:a45b with SMTP id ffacd0b85a97d-386453d7028mr147798f8f.21.1733747901284; Mon, 09 Dec 2024 04:38:21 -0800 (PST) X-Google-Smtp-Source: AGHT+IEYHxKVPJ2qgAv7OqhotIxo6X4rQdCFyymxlIv8luqWuHEFXSvvl8hVztzNVTYO4jP+aAsfAw== X-Received: by 2002:a05:6000:1fa5:b0:385:f00a:a45b with SMTP id ffacd0b85a97d-386453d7028mr147778f8f.21.1733747900821; Mon, 09 Dec 2024 04:38:20 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 25/26] rust: qemu-api: add a module to wrap functions and zero-sized closures Date: Mon, 9 Dec 2024 13:37:16 +0100 Message-ID: <20241209123717.99077-26-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=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: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733748215394116600 Content-Type: text/plain; charset="utf-8" One recurring issue when writing Rust bindings is how to convert a Rust function ("fn" or "impl Fn") to a C function, and how to pass around "self" to a C function that only takes a void*. An easy solution would be to store on the heap a pair consisting of a pointer to the Rust function and the pointer to "self", but it is possible to do better. If an "Fn" has zero size (that is, if it is a zero-capture closures or a function pointer---which in turn includes all methods), it is possible to build a generic Rust function that calls it even if you only have the type; you don't need either the pointer to the function itself (because the address of the code is part of the type) or any closure data (because it has size zero). Introduce a wrapper that provides the functionality of calling the function given only its type. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Zhao Liu <zhao1.liu@intel.com> --- rust/qemu-api/meson.build | 1 + rust/qemu-api/src/callbacks.rs | 141 +++++++++++++++++++++++++++++++++ rust/qemu-api/src/lib.rs | 1 + 3 files changed, 143 insertions(+) create mode 100644 rust/qemu-api/src/callbacks.rs diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build index 7ff408ad68e..8c82c5e96c2 100644 --- a/rust/qemu-api/meson.build +++ b/rust/qemu-api/meson.build @@ -17,6 +17,7 @@ _qemu_api_rs =3D static_library( 'src/lib.rs', 'src/bindings.rs', 'src/bitops.rs', + 'src/callbacks.rs', 'src/cell.rs', 'src/c_str.rs', 'src/irq.rs', diff --git a/rust/qemu-api/src/callbacks.rs b/rust/qemu-api/src/callbacks.rs new file mode 100644 index 00000000000..6401d807198 --- /dev/null +++ b/rust/qemu-api/src/callbacks.rs @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: MIT + +//! Utility functions to deal with callbacks from C to Rust. + +use std::{mem, ptr::NonNull}; + +/// Trait for functions (types implementing [`Fn`]) that can be used as +/// callbacks. These include both zero-capture closures and function point= ers. +/// +/// In Rust, calling a function through the `Fn` trait normally requires a +/// `self` parameter, even though for zero-sized functions (including func= tion +/// pointers) the type itself contains all necessary information to call t= he +/// function. This trait provides a `call` function that doesn't require `= self`, +/// allowing zero-sized functions to be called using only their type. +/// +/// This enables zero-sized functions to be passed entirely through generic +/// parameters and resolved at compile-time. A typical use is a function +/// receiving an unused parameter of generic type `F` and calling it via +/// `F::call` or passing it to another function via `func::<F>`. +/// +/// QEMU uses this trick to create wrappers to C callbacks. The wrappers +/// are needed to convert an opaque `*mut c_void` into a Rust reference, +/// but they only have a single opaque that they can use. The `FnCall` +/// trait makes it possible to use that opaque for `self` or any other +/// reference: +/// +/// ```ignore +/// // The compiler creates a new `rust_bh_cb` wrapper for each function +/// // passed to `qemu_bh_schedule_oneshot` below. +/// unsafe extern "C" fn rust_bh_cb<T, F: for<'a> FnCall<(&'a T,)>>( +/// opaque: *mut c_void, +/// ) { +/// // SAFETY: the opaque was passed as a reference to `T`. +/// F::call((unsafe { &*(opaque.cast::<T>()) }, )) +/// } +/// +/// // The `_f` parameter is unused but it helps the compiler build the ap= propriate `F`. +/// // Using a reference allows usage in const context. +/// fn qemu_bh_schedule_oneshot<T, F: for<'a> FnCall<(&'a T,)>>(_f: &F, op= aque: &T) { +/// let cb: unsafe extern "C" fn(*mut c_void) =3D rust_bh_cb::<T, F>; +/// unsafe { +/// bindings::qemu_bh_schedule_oneshot(cb, opaque as *const T as *= const c_void as *mut c_void) +/// } +/// } +/// ``` +/// +/// Each wrapper is a separate instance of `rust_bh_cb` and is therefore +/// compiled to a separate function ("monomorphization"). If you wanted +/// to pass `self` as the opaque value, the generic parameters would be +/// `rust_bh_cb::<Self, F>`. +/// +/// `Args` is a tuple type whose types are the arguments of the function, +/// while `R` is the returned type. +/// +/// # Examples +/// +/// ``` +/// # use qemu_api::callbacks::FnCall; +/// fn call_it<F: for<'a> FnCall<(&'a str,), String>>(_f: &F, s: &str) -> = String { +/// F::call((s,)) +/// } +/// +/// let s: String =3D call_it(&str::to_owned, "hello world"); +/// assert_eq!(s, "hello world"); +/// ``` +/// +/// Note that the compiler will produce a different version of `call_it` f= or +/// each function that is passed to it. Therefore the argument is not rea= lly +/// used, except to decide what is `F` and what `F::call` does. +/// +/// Attempting to pass a non-zero-sized closure causes a compile-time fail= ure: +/// +/// ```compile_fail +/// # use qemu_api::callbacks::FnCall; +/// # fn call_it<'a, F: FnCall<(&'a str,), String>>(_f: &F, s: &'a str) ->= String { +/// # F::call((s,)) +/// # } +/// let x: &'static str =3D "goodbye world"; +/// call_it(&move |_| String::from(x), "hello workd"); +/// ``` +/// +/// # Safety +/// +/// Because `Self` is a zero-sized type, all instances of the type are +/// equivalent. However, in addition to this, `Self` must have no invarian= ts +/// that could be violated by creating a reference to it. +/// +/// This is always true for zero-capture closures and function pointers, a= s long +/// as the code is able to name the function in the first place. +pub unsafe trait FnCall<Args, R =3D ()>: 'static + Sync + Sized { + /// Referring to this internal constant asserts that the `Self` type is + /// zero-sized. Can be replaced by an inline const expression in + /// Rust 1.79.0+. + const ASSERT_ZERO_SIZED: () =3D { assert!(mem::size_of::<Self>() =3D= =3D 0) }; + + /// Call the function with the arguments in args. + fn call(a: Args) -> R; +} + +macro_rules! impl_call { + ($($args:ident,)* ) =3D> ( + // SAFETY: because each function is treated as a separate type, + // accessing `FnCall` is only possible in code that would be + // allowed to call the function. + unsafe impl<F, $($args,)* R> FnCall<($($args,)*), R> for F + where + F: 'static + Sync + Sized + Fn($($args, )*) -> R, + { + #[inline(always)] + fn call(a: ($($args,)*)) -> R { + let _: () =3D Self::ASSERT_ZERO_SIZED; + + // SAFETY: the safety of this method is the condition for = implementing + // `FnCall`. As to the `NonNull` idiom to create a zero-s= ized type, + // see https://github.com/rust-lang/libs-team/issues/292. + let f: &'static F =3D unsafe { &*NonNull::<Self>::dangling= ().as_ptr() }; + let ($($args,)*) =3D a; + f($($args,)*) + } + } + ) +} + +impl_call!(_1, _2, _3, _4, _5,); +impl_call!(_1, _2, _3, _4,); +impl_call!(_1, _2, _3,); +impl_call!(_1, _2,); +impl_call!(_1,); +impl_call!(); + +#[cfg(test)] +mod tests { + use super::*; + + // The `_f` parameter is unused but it helps the compiler infer `F`. + fn do_test_call<'a, F: FnCall<(&'a str,), String>>(_f: &F) -> String { + F::call(("hello world",)) + } + + #[test] + fn test_call() { + assert_eq!(do_test_call(&str::to_owned), "hello world") + } +} diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs index 124bece0449..4b43e02c0f9 100644 --- a/rust/qemu-api/src/lib.rs +++ b/rust/qemu-api/src/lib.rs @@ -14,6 +14,7 @@ =20 pub mod bitops; pub mod c_str; +pub mod callbacks; pub mod cell; pub mod irq; pub mod module; --=20 2.47.1 From nobody Sun May 11 09:25:34 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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1733748762; cv=none; d=zohomail.com; s=zohoarc; b=EVU8g6PDmyF6Dbgun56XI37w7A7hndseSjHA7+fuZcnP1+z2ebh/lKMJecyhvGNuPU8iqj5hWr9++jukFZcZ7ZYNAiYTsIdiLLhd2X501i8kCXujq8bbw7mUtLMYVIz8juqurwNwn3yhbbCUC8o/1a0//sMfJzXPTlAyACM6rn8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1733748762; 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=T6KMN/KKwz/drY0m0B/GAzuPFwO/9IuBICqSOgF3wlY=; b=jHm/uS6kbcQn/wR8fhEvfzv5hXqNyAAEVWojxHoeHq05wFhZaSLFQ3hf35qKSAgO9BVAMMS8pYxlGZIDvM0MbbeIZP1vKjlgKbNhoOJ1FNhYsg8/DbBYtHcVLocf1GajY1S1u6bxrs40+frHDkL2IYz904D6TLJWhzaVoouNM6U= 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=<pbonzini@redhat.com> (p=none dis=none) Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1733748762327545.117793203575; Mon, 9 Dec 2024 04:52:42 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <qemu-devel-bounces@nongnu.org>) id 1tKd6X-0008CP-6a; Mon, 09 Dec 2024 07:43:17 -0500 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 <pbonzini@redhat.com>) id 1tKd22-0004Yy-HA for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:42 -0500 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 <pbonzini@redhat.com>) id 1tKd1w-0007as-Cp for qemu-devel@nongnu.org; Mon, 09 Dec 2024 07:38:33 -0500 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-529-5SkZ6bASP8uC9z-rmISFqw-1; Mon, 09 Dec 2024 07:38:25 -0500 Received: by mail-wr1-f70.google.com with SMTP id ffacd0b85a97d-3862c67763dso1816110f8f.3 for <qemu-devel@nongnu.org>; Mon, 09 Dec 2024 04:38:25 -0800 (PST) Received: from [192.168.10.47] ([151.81.118.45]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-434f0d6a825sm71952995e9.20.2024.12.09.04.38.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 04:38:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733747906; 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=T6KMN/KKwz/drY0m0B/GAzuPFwO/9IuBICqSOgF3wlY=; b=KjystAASfB/h9av5tZ4PqlUtqDOIdjs5sFHfASFI6EqzOxY3DnpOoUOI4zQWk+o9JqSK8F 3DD4IdZHVgO5yepdKJEyTTgnZOEvNjeQBRNG/k/Lv8wwPoa+U5M5FwRmOG9dgmh1MkJzgx VIm4k+fG7Bjbc8EDOy/oaoUCJgxHHYY= X-MC-Unique: 5SkZ6bASP8uC9z-rmISFqw-1 X-Mimecast-MFC-AGG-ID: 5SkZ6bASP8uC9z-rmISFqw X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733747903; x=1734352703; 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=T6KMN/KKwz/drY0m0B/GAzuPFwO/9IuBICqSOgF3wlY=; b=DoQNFmnxVkZyq84e06+Gp2s+cSEdkDSh16j4+S5nQyeE3FOe5atwpMrxtaf/7oqL00 zN0htOhSB/qAeNW1e8SBrU7PyhKq9I71JUlIzR7YweZMu/emFgmbJnmoLv4MZ8yXBKOE FZQpwxOTBnwzQQW1r7vdQAc0w+zkcsneKL11xnYo6+SKf5GftJCny5gNndzUjLxY0/eM W6OGY8pxfRMX+OXe36OqKlKeJehX1mGJWmcFvpn7JuvODAbmrEE3Xd+TS190Q+OyRjZe JhVKidkVEMRzaf2ZtFTdj61ct0UQ5rDilyAUIuYIvobC2nCQug1RPwcQY/DHPMh3tVq5 Un+Q== X-Gm-Message-State: AOJu0YwW6TR622/DsIfJO/wGENb/Tfsii523q/iF25Effi29ctFqzAR3 9f6/Z9RFrOFa3/pCnomJYNuJURaCgGWKUUlI+hOPmc2neTbLmlQW4g96eZzN1lpVbhBoLyk4C3u vbRj+rvGBHEW+Kk4CUnU/O7190/nqz1VdMzJaGT6on9i2kQvW7vRbapMWqxbXEmkXZA/RmRPiEO 1xd7dIFb0TJLjHlQAL7z86cNFTCWozJnvZTvhe X-Gm-Gg: ASbGnct+stPTvPYTKvNNqnW0QoCcXcn3gUTELjisBmA6Z9V9T6J4H4UcUZm/iMCed9u R54jebc4HRwIsvVI6HW03kTmnW6FBQxLwHgfYS4jRn5yFVW3R8J8j3wkcWIfh8z35OnpMzF/sae Qzvy+c2Ng+Rc33kWWFmi6Et/wzIAbg33/AGLY4mg1cdTanZ8Spz9ZQg6k2L6gYaKOQG5Ht7uGeR ENbnNnnEsVd55haykpvIUGpfRvdVL1tepFrbjid1ZRwpBFOym6uoA== X-Received: by 2002:a05:6000:4715:b0:385:fb34:d585 with SMTP id ffacd0b85a97d-3862b37f1fcmr9529702f8f.34.1733747903513; Mon, 09 Dec 2024 04:38:23 -0800 (PST) X-Google-Smtp-Source: AGHT+IHNIjYvCBUUw5SuI6EdubzMkYBb+V9p2OLC1S6N1gh//MaK5456gKjpwFzm1ivquRIqCgHGWg== X-Received: by 2002:a05:6000:4715:b0:385:fb34:d585 with SMTP id ffacd0b85a97d-3862b37f1fcmr9529680f8f.34.1733747903085; Mon, 09 Dec 2024 04:38:23 -0800 (PST) From: Paolo Bonzini <pbonzini@redhat.com> To: qemu-devel@nongnu.org Cc: qemu-rust@nongnu.org, Zhao Liu <zhao1.liu@intel.com>, Junjie Mao <junjie.mao@hotmail.com> Subject: [PATCH 26/26] rust: callbacks: allow passing optional callbacks as () Date: Mon, 9 Dec 2024 13:37:17 +0100 Message-ID: <20241209123717.99077-27-pbonzini@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241209123717.99077-1-pbonzini@redhat.com> References: <20241209123717.99077-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: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.489, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <https://lists.nongnu.org/archive/html/qemu-devel> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=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: 1733748859389116600 Content-Type: text/plain; charset="utf-8" In some cases, callbacks are optional. Using "Some(function)" and "None" does not work well, because when someone writes "None" the compiler does not know what to use for "F" in "Option<F>". Therefore, adopt () to mean a "null" callback. It is possible to enforce that a callback is valid by adding a "let _: () =3D F::ASSERT_IS_SOME" befo= re the invocation of F::call. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- rust/qemu-api/src/callbacks.rs | 97 ++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/rust/qemu-api/src/callbacks.rs b/rust/qemu-api/src/callbacks.rs index 6401d807198..83c681d6478 100644 --- a/rust/qemu-api/src/callbacks.rs +++ b/rust/qemu-api/src/callbacks.rs @@ -76,6 +76,31 @@ /// call_it(&move |_| String::from(x), "hello workd"); /// ``` /// +/// `()` can be used to indicate "no function": +/// +/// ``` +/// # use qemu_api::callbacks::FnCall; +/// fn optional<F: for<'a> FnCall<(&'a str,), String>>(_f: &F, s: &str) ->= Option<String> { +/// if F::IS_SOME { +/// Some(F::call((s,))) +/// } else { +/// None +/// } +/// } +/// +/// assert!(optional(&(), "hello world").is_none()); +/// ``` +/// +/// Invoking `F::call` will then be a run-time error. +/// +/// ```should_panic +/// # use qemu_api::callbacks::FnCall; +/// # fn call_it<F: for<'a> FnCall<(&'a str,), String>>(_f: &F, s: &str) -= > String { +/// # F::call((s,)) +/// # } +/// let s: String =3D call_it(&(), "hello world"); // panics +/// ``` +/// /// # Safety /// /// Because `Self` is a zero-sized type, all instances of the type are @@ -90,10 +115,70 @@ pub unsafe trait FnCall<Args, R =3D ()>: 'static + Syn= c + Sized { /// Rust 1.79.0+. const ASSERT_ZERO_SIZED: () =3D { assert!(mem::size_of::<Self>() =3D= =3D 0) }; =20 + /// Referring to this constant asserts that the `Self` type is an actu= al + /// function type, which can be used to catch incorrect use of `()` + /// at compile time. + /// + /// # Examples + /// + /// ```compile_fail + /// # use qemu_api::callbacks::FnCall; + /// fn call_it<F: for<'a> FnCall<(&'a str,), String>>(_f: &F, s: &str)= -> String { + /// let _: () =3D F::ASSERT_IS_SOME; + /// F::call((s,)) + /// } + /// + /// let s: String =3D call_it((), "hello world"); // does not compile + /// ``` + /// + /// Note that this use more simply `const { assert!(F::IS_SOME) }` in + /// Rust 1.79.0 or newer. + const ASSERT_IS_SOME: () =3D { assert!(Self::IS_SOME) }; + + /// `true` if `Self` is an actual function type and not `()`. + /// + /// # Examples + /// + /// You can use `IS_SOME` to catch this at compile time: + /// + /// ```compile_fail + /// # use qemu_api::callbacks::FnCall; + /// fn call_it<F: for<'a> FnCall<(&'a str,), String>>(_f: &F, s: &str)= -> String { + /// const { assert!(F::IS_SOME) } + /// F::call((s,)) + /// } + /// + /// let s: String =3D call_it((), "hello world"); // does not compile + /// ``` + const IS_SOME: bool; + + /// `false` if `Self` is an actual function type, `true` if it is `()`. + fn is_none() -> bool { + !Self::IS_SOME + } + + /// `true` if `Self` is an actual function type, `false` if it is `()`. + fn is_some() -> bool { + Self::IS_SOME + } + /// Call the function with the arguments in args. fn call(a: Args) -> R; } =20 +/// `()` acts as a "null" callback. Using `()` and `function` is nicer +/// than `None` and `Some(function)`, because the compiler is unable to +/// infer the type of just `None`. Therefore, the trait itself acts as the +/// option type, with functions [`FnCall::is_some`] and [`FnCall::is_none`= ]. +unsafe impl<Args, R> FnCall<Args, R> for () { + const IS_SOME: bool =3D false; + + /// Call the function with the arguments in args. + fn call(_a: Args) -> R { + panic!("callback not specified") + } +} + macro_rules! impl_call { ($($args:ident,)* ) =3D> ( // SAFETY: because each function is treated as a separate type, @@ -103,6 +188,8 @@ unsafe impl<F, $($args,)* R> FnCall<($($args,)*), R> fo= r F where F: 'static + Sync + Sized + Fn($($args, )*) -> R, { + const IS_SOME: bool =3D true; + #[inline(always)] fn call(a: ($($args,)*)) -> R { let _: () =3D Self::ASSERT_ZERO_SIZED; @@ -138,4 +225,14 @@ fn do_test_call<'a, F: FnCall<(&'a str,), String>>(_f:= &F) -> String { fn test_call() { assert_eq!(do_test_call(&str::to_owned), "hello world") } + + // The `_f` parameter is unused but it helps the compiler infer `F`. + fn do_test_is_some<'a, F: FnCall<(&'a str,), String>>(_f: &F) { + assert_eq!(F::is_some(), true); + } + + #[test] + fn test_is_some() { + do_test_is_some(&str::to_owned); + } } --=20 2.47.1