From nobody Sun Sep 28 16:37:06 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1758550878; cv=none; d=zohomail.com; s=zohoarc; b=aOVllsaXtGPk9roKe7EwIdHoXi6iMMGUFe+zquLK9x4wxoWgWrFo9GYU+byS6vnd/xq33UGcoOqbn1fXCq835N0IvDuaNHdSavsz3PYhx1dv6Xzbs9KBwwxlqa1bhN17ikXTx/SvkqheTL3Q2x6gtHg+pUSnG6rxOnNsCjWHZ9A= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1758550878; 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=1AlLCCUVEtMh667ur4PFbdsy/38i8N9FkxZSDHHo0/w=; b=J0HqcGhl4oLy9qYaYjqm57gWwOag2BTT4jlpUSh5urPM/7U1yiGCjA6ApA+SCmLpEpev7LcqPBRsozLo8m+OemOG7NzJX8/n790m8H1/GnyV/8zhqXpWYBBu/fD6ajihDbgGUSs8xzinO/fj7X2flXG1UpfM/Iir3pncMiBDNxY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758550878055783.7522571928748; Mon, 22 Sep 2025 07:21:18 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v0hOi-0006jb-Bw; Mon, 22 Sep 2025 10:20:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v0hOX-0006bB-Ev for qemu-devel@nongnu.org; Mon, 22 Sep 2025 10:20:00 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v0hOU-0006mT-1U for qemu-devel@nongnu.org; Mon, 22 Sep 2025 10:19:57 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-677-6AJeNFg1PeySlEErvDBwOg-1; Mon, 22 Sep 2025 10:19:48 -0400 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 6CA3D18004D4; Mon, 22 Sep 2025 14:19:47 +0000 (UTC) Received: from gerbillo.redhat.com (unknown [10.44.32.247]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 7BF5119560BB; Mon, 22 Sep 2025 14:19:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1758550792; 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=1AlLCCUVEtMh667ur4PFbdsy/38i8N9FkxZSDHHo0/w=; b=AFpokm/8d7YrNmGshkXn2vTJUYiOazXczXdxa9axZS/vIT6pZsY5xyjpXbPPZwzI1QjsV2 AS2uQQ2PPm6S/C0prAklQPmkltDI4p+dpxzUoYlpfHm+KjruPh3cSDz6eXG60TQxBtzyVb 8lllppfkOtv1ANhDxq6ErlWvpAD+VZ8= X-MC-Unique: 6AJeNFg1PeySlEErvDBwOg-1 X-Mimecast-MFC-AGG-ID: 6AJeNFg1PeySlEErvDBwOg_1758550787 From: Paolo Abeni To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Dmitry Fleytman , Akihiko Odaki , Jason Wang , Sriram Yagnaraman , "Michael S. Tsirkin" , Stefano Garzarella , Cornelia Huck , Luigi Rizzo , Giuseppe Lettieri , Vincenzo Maffione , Eric Blake , Markus Armbruster Subject: [PATCH v7 07/14] virtio-pci: implement support for extended features Date: Mon, 22 Sep 2025 16:18:21 +0200 Message-ID: In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 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=pabeni@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -24 X-Spam_score: -2.5 X-Spam_bar: -- X-Spam_report: (-2.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.442, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1758550879418116600 Content-Type: text/plain; charset="utf-8" Extend the features configuration space to 128 bits. If the virtio device supports any extended features, allow the common read/write operation to access all of it, otherwise keep exposing only the lower 64 bits. On migration, save the 128 bit version of the features only if the upper bits are non zero. Relay on reset to clear all the feature space before load. Reviewed-by: Akihiko Odaki Acked-by: Jason Wang Acked-by: Stefano Garzarella Signed-off-by: Paolo Abeni --- v5 -> v6: - fixed checkpatch error (missing brackets on a single line statement) v4 -> v5: - add blank line after QEMU_BUILD_BUG_ON() - make virtio_pci_select_max() robust vs future feature space increase v3 -> v4: - use new virtio_features macro names - move the build bug before vmstate_virtio_pci_modern_state_sub v2 -> v3: - drop the pre_load/post_load trickery and relay on reset zeroing the features instead. - avoid union usage, just increase guest_features size and use SUB_ARRAY. - drop unneeded '!!' - _array -> _ex v1 -> v2: - use separate VMStateDescription and pre/post load to avoid breaking migration - clear proxy features on device reset --- hw/virtio/virtio-pci.c | 76 ++++++++++++++++++++++++++++++---- include/hw/virtio/virtio-pci.h | 2 +- 2 files changed, 68 insertions(+), 10 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 767216d795..01e4fecaf4 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -109,6 +109,29 @@ static const VMStateDescription vmstate_virtio_pci_mod= ern_queue_state =3D { } }; =20 +static bool virtio_pci_modern_state_features128_needed(void *opaque) +{ + VirtIOPCIProxy *proxy =3D opaque; + uint32_t features =3D 0; + int i; + + for (i =3D 2; i < ARRAY_SIZE(proxy->guest_features); ++i) { + features |=3D proxy->guest_features[i]; + } + return features; +} + +static const VMStateDescription vmstate_virtio_pci_modern_state_features12= 8 =3D { + .name =3D "virtio_pci/modern_state/features128", + .version_id =3D 1, + .minimum_version_id =3D 1, + .needed =3D &virtio_pci_modern_state_features128_needed, + .fields =3D (const VMStateField[]) { + VMSTATE_UINT32_SUB_ARRAY(guest_features, VirtIOPCIProxy, 2, 2), + VMSTATE_END_OF_LIST() + } +}; + static bool virtio_pci_modern_state_needed(void *opaque) { VirtIOPCIProxy *proxy =3D opaque; @@ -116,6 +139,12 @@ static bool virtio_pci_modern_state_needed(void *opaqu= e) return virtio_pci_modern(proxy); } =20 +/* + * Avoid silently breaking migration should the feature space increase + * even more in the (far away) future + */ +QEMU_BUILD_BUG_ON(VIRTIO_FEATURES_NU32S !=3D 4); + static const VMStateDescription vmstate_virtio_pci_modern_state_sub =3D { .name =3D "virtio_pci/modern_state", .version_id =3D 1, @@ -124,11 +153,15 @@ static const VMStateDescription vmstate_virtio_pci_mo= dern_state_sub =3D { .fields =3D (const VMStateField[]) { VMSTATE_UINT32(dfselect, VirtIOPCIProxy), VMSTATE_UINT32(gfselect, VirtIOPCIProxy), - VMSTATE_UINT32_ARRAY(guest_features, VirtIOPCIProxy, 2), + VMSTATE_UINT32_SUB_ARRAY(guest_features, VirtIOPCIProxy, 0, 2), VMSTATE_STRUCT_ARRAY(vqs, VirtIOPCIProxy, VIRTIO_QUEUE_MAX, 0, vmstate_virtio_pci_modern_queue_state, VirtIOPCIQueue), VMSTATE_END_OF_LIST() + }, + .subsections =3D (const VMStateDescription * const []) { + &vmstate_virtio_pci_modern_state_features128, + NULL } }; =20 @@ -1477,6 +1510,19 @@ int virtio_pci_add_shm_cap(VirtIOPCIProxy *proxy, return virtio_pci_add_mem_cap(proxy, &cap.cap); } =20 +static int virtio_pci_select_max(const VirtIODevice *vdev) +{ + int i; + + for (i =3D VIRTIO_FEATURES_NU64S - 1; i > 0; i--) { + if (vdev->host_features_ex[i]) { + return (i + 1) * 2; + } + } + + return 2; +} + static uint64_t virtio_pci_common_read(void *opaque, hwaddr addr, unsigned size) { @@ -1494,18 +1540,21 @@ static uint64_t virtio_pci_common_read(void *opaque= , hwaddr addr, val =3D proxy->dfselect; break; case VIRTIO_PCI_COMMON_DF: - if (proxy->dfselect <=3D 1) { + if (proxy->dfselect < virtio_pci_select_max(vdev)) { VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_GET_CLASS(vdev); =20 - val =3D (vdev->host_features & ~vdc->legacy_features) >> - (32 * proxy->dfselect); + val =3D vdev->host_features_ex[proxy->dfselect >> 1] >> + (32 * (proxy->dfselect & 1)); + if (proxy->dfselect <=3D 1) { + val &=3D (~vdc->legacy_features) >> (32 * proxy->dfselect); + } } break; case VIRTIO_PCI_COMMON_GFSELECT: val =3D proxy->gfselect; break; case VIRTIO_PCI_COMMON_GF: - if (proxy->gfselect < ARRAY_SIZE(proxy->guest_features)) { + if (proxy->gfselect < virtio_pci_select_max(vdev)) { val =3D proxy->guest_features[proxy->gfselect]; } break; @@ -1588,11 +1637,18 @@ static void virtio_pci_common_write(void *opaque, h= waddr addr, proxy->gfselect =3D val; break; case VIRTIO_PCI_COMMON_GF: - if (proxy->gfselect < ARRAY_SIZE(proxy->guest_features)) { + if (proxy->gfselect < virtio_pci_select_max(vdev)) { + uint64_t features[VIRTIO_FEATURES_NU64S]; + int i; + proxy->guest_features[proxy->gfselect] =3D val; - virtio_set_features(vdev, - (((uint64_t)proxy->guest_features[1]) << 3= 2) | - proxy->guest_features[0]); + virtio_features_clear(features); + for (i =3D 0; i < ARRAY_SIZE(proxy->guest_features); ++i) { + uint64_t cur =3D proxy->guest_features[i]; + + features[i >> 1] |=3D cur << ((i & 1) * 32); + } + virtio_set_features_ex(vdev, features); } break; case VIRTIO_PCI_COMMON_MSIX: @@ -2311,6 +2367,8 @@ static void virtio_pci_reset(DeviceState *qdev) virtio_bus_reset(bus); msix_unuse_all_vectors(&proxy->pci_dev); =20 + memset(proxy->guest_features, 0, sizeof(proxy->guest_features)); + for (i =3D 0; i < VIRTIO_QUEUE_MAX; i++) { proxy->vqs[i].enabled =3D 0; proxy->vqs[i].reset =3D 0; diff --git a/include/hw/virtio/virtio-pci.h b/include/hw/virtio/virtio-pci.h index eab5394898..639752977e 100644 --- a/include/hw/virtio/virtio-pci.h +++ b/include/hw/virtio/virtio-pci.h @@ -158,7 +158,7 @@ struct VirtIOPCIProxy { uint32_t nvectors; uint32_t dfselect; uint32_t gfselect; - uint32_t guest_features[2]; + uint32_t guest_features[VIRTIO_FEATURES_NU32S]; VirtIOPCIQueue vqs[VIRTIO_QUEUE_MAX]; =20 VirtIOIRQFD *vector_irqfd; --=20 2.51.0