Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2174155/?format=api
{ "id": 2174155, "url": "http://patchwork.ozlabs.org/api/patches/2174155/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20251215075902.2428-1-wafer@jaguarmicro.com/", "project": { "id": 14, "url": "http://patchwork.ozlabs.org/api/projects/14/?format=api", "name": "QEMU Development", "link_name": "qemu-devel", "list_id": "qemu-devel.nongnu.org", "list_email": "qemu-devel@nongnu.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20251215075902.2428-1-wafer@jaguarmicro.com>", "list_archive_url": null, "date": "2025-12-15T07:59:02", "name": "[v2,4/4] vhost: SVQ add the indirect descriptors to available ring", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "41148a16d665db3e40f50607b93bd3af5a5432b7", "submitter": { "id": 87629, "url": "http://patchwork.ozlabs.org/api/people/87629/?format=api", "name": "Wafer", "email": "wafer@jaguarmicro.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20251215075902.2428-1-wafer@jaguarmicro.com/mbox/", "series": [ { "id": 485358, "url": "http://patchwork.ozlabs.org/api/series/485358/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=485358", "date": "2025-12-15T07:57:13", "name": "[v2,1/4] vhost: add data structure of virtio indirect descriptors in SVQ", "version": 2, "mbox": "http://patchwork.ozlabs.org/series/485358/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2174155/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2174155/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=jaguarmicro.com header.i=@jaguarmicro.com\n header.a=rsa-sha256 header.s=selector2 header.b=KylFaGyf;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)", "dkim=none (message not signed)\n header.d=none;dmarc=none action=none header.from=jaguarmicro.com;" ], "Received": [ "from lists.gnu.org (lists.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4dVCBs0NXQz1xyL\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 15 Dec 2025 18:59:32 +1100 (AEDT)", "from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1vV3UI-0008GK-QX; Mon, 15 Dec 2025 02:59:22 -0500", "from eggs.gnu.org ([2001:470:142:3::10])\n by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <wafer@jaguarmicro.com>)\n id 1vV3UH-0008Fq-6t\n for qemu-devel@nongnu.org; Mon, 15 Dec 2025 02:59:21 -0500", "from mail-japanwestazlp170120003.outbound.protection.outlook.com\n ([2a01:111:f403:c406::3] helo=OS8PR02CU002.outbound.protection.outlook.com)\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <wafer@jaguarmicro.com>)\n id 1vV3UF-0004Hr-1x\n for qemu-devel@nongnu.org; Mon, 15 Dec 2025 02:59:20 -0500", "from PUZPR06MB4713.apcprd06.prod.outlook.com (2603:1096:301:b4::10)\n by OSNPR06MB8228.apcprd06.prod.outlook.com (2603:1096:604:45e::6)\n with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9412.13; Mon, 15 Dec\n 2025 07:59:13 +0000", "from PUZPR06MB4713.apcprd06.prod.outlook.com\n ([fe80::1b36:28b0:4e5:de66]) by PUZPR06MB4713.apcprd06.prod.outlook.com\n ([fe80::1b36:28b0:4e5:de66%6]) with mapi id 15.20.9412.011; Mon, 15 Dec 2025\n 07:59:13 +0000" ], "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;\n b=MY99IYz6fMZvoO4BuBBO+5U/NN4KGGBDpHPRiY3UmAQ4LDcS93WDX9aDr9dGvMyGR68mViAurXz/d8VKFvdDwD+tB/USghRFI75xcJfUbFQcLznD9UtFPDR58Km9Fr2meOsZMNaiN3rJbFdj45P+zIlISXLvsXwBftBXxEJ9g+kREKRQdbimeIEhObRka/WxQoYfywJLg7iRwg9zQHLvPCh4LZpQGvH/4ceV/ewwzAjiu0XSOtcUr+DqNQUUDNap2iZ1dmdCPNAZIFFL+CLE8b3bulzatk0gbmb5LRlZlf0ZnN1UPtCuptnVmQS7UlsfHM1MApmJ7tDziVBhCrAYtQ==", "ARC-Message-Signature": "i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;\n s=arcselector10001;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;\n bh=K8twKTd3sJEqpcDsBLwJRuzOM52cnv/phGQt4VjSEow=;\n b=RnIHuoNmgqyXkTlvMMyPAKa0uhhvs2ygNR0M2as4pkAPB9jqKKQVK/lN6GoJhjlerXHLESTeUnvhoIokP2viFU98zzBQP9qFTJuyA1/yJnF7qYktmBE7a/Xhrx+0DhohrArybmL5D+D3Z3cOP+72aaB5Vk7iVGLseMhQbdybO/vkh0zLhEZt5v8JabnkEp+Td7Ozyj5bC1Ein55avct2ddAN3HCMh9RGWr94Jsy9FytkdVLxggzMEE5CMZyJzqgaaLzyvxHe2fwhkdNQavPWx7j0KRHrDdLPNpzX9JoXvno3zZOW6C+h64T2DtXoLy2bUB/yRkVd2ShbiWB/mvAQvQ==", "ARC-Authentication-Results": "i=1; mx.microsoft.com 1; spf=pass\n smtp.mailfrom=jaguarmicro.com; dmarc=pass action=none\n header.from=jaguarmicro.com; dkim=pass header.d=jaguarmicro.com; arc=none", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=jaguarmicro.com;\n s=selector2;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=K8twKTd3sJEqpcDsBLwJRuzOM52cnv/phGQt4VjSEow=;\n b=KylFaGyfqe9Z5QRjConEknpVjencqnh0xNRwVxt9loj7qn/QBT+6wLxOsEz/zxRVRety/w8YTDb6dJQRQDSTt0YGOzZrOd5ddFM2q1U8x3+v9+Pr558ct2CTSTre8UgB7jYze3FyR0EAgGlSoYPEE8VCGmQv2GL+pgYmiMGGWpG6+69F6BatgD2kdGl0TOLNjiHSHjIOXnoy9Vy5ZEIE93NsGIxmGP4hw7vMBzYGIEJcJx7DfatvrW+JWf2gcnJFSI5UJ2NbW+jf6S48bYN+XeVRuNU7MXYteuGDjGGrlYvJwfKZdJZM7AKjFWRjqbX5uItxcwA/8sJnxWOGPxM6uw==", "From": "Wafer Xie <wafer@jaguarmicro.com>", "To": "mst@redhat.com, eperezma@redhat.com, jasowang@redhat.com,\n qemu-devel@nongnu.org", "Cc": "leiyang@redhat.com, sgarzare@redhat.com, angus.chen@jaguarmicro.com,\n wafer@jaguarmicro.com", "Subject": "[PATCH v2 4/4] vhost: SVQ add the indirect descriptors to available\n ring", "Date": "Mon, 15 Dec 2025 15:59:02 +0800", "Message-Id": "<20251215075902.2428-1-wafer@jaguarmicro.com>", "X-Mailer": "git-send-email 2.34.1", "Content-Type": "text/plain; charset=UTF-8", "Content-Transfer-Encoding": "8bit", "X-ClientProxiedBy": "KU0P306CA0063.MYSP306.PROD.OUTLOOK.COM\n (2603:1096:d10:23::11) To PUZPR06MB4713.apcprd06.prod.outlook.com\n (2603:1096:301:b4::10)", "MIME-Version": "1.0", "X-MS-PublicTrafficType": "Email", "X-MS-TrafficTypeDiagnostic": "PUZPR06MB4713:EE_|OSNPR06MB8228:EE_", "X-MS-Office365-Filtering-Correlation-Id": "5d48c659-627b-4254-17bf-08de3bafd60e", "X-MS-Exchange-SenderADCheck": "1", "X-MS-Exchange-AntiSpam-Relay": "0", "X-Microsoft-Antispam": "BCL:0;\n ARA:13230040|1800799024|376014|52116014|366016|38350700014;", "X-Microsoft-Antispam-Message-Info": "=?utf-8?q?mPt4Vxtr1+s0X8FP8CFF1l4Rj6MqiVo?=\n\t=?utf-8?q?uSEs1sGZ7pVpHWHV+OMQr5vQWznOb3fa0RhBAfb7VHYqOBImVtb6xYrNQiV5N5Rth?=\n\t=?utf-8?q?vhKe7Mlorb+TDwzgEzhCm8mbCoImn2Zl+BT4QEqNnQXv1v2fcaV8AWWzjyZqXBLyz?=\n\t=?utf-8?q?u575pIOm1fInHTwriVSQ6rgdp5+WecTOCHMK5+mKztxA0MaI23VfnyWFbXqsXIXJy?=\n\t=?utf-8?q?aYNl8klK/iYyP7yvoLWsKy3MBosNDQsT20nwZoHjS07ikI+mopg6srukLxMpOaYEa?=\n\t=?utf-8?q?mUlL6gKZFpbbgnUcxoXccG/spHwnnUueH6DO7KPlglfVHyiu9yp06CSgg+VN7kA8Y?=\n\t=?utf-8?q?SXmU8toyOXCJElJAFjqs/B10aWJdAs0jPML/QlhBB2hMDqIJvYr5HoEPPestSS7dI?=\n\t=?utf-8?q?WEkeIMFVADNgTsyrw8nv+pYSdu06+Z+gDq+e0Ot7iCzpHB/mDONMKMGvPwnaA7KmJ?=\n\t=?utf-8?q?75VYVBNFbyTbEQQ/ACYsc8f2T8c1lteSOCCov26W9Nwz7BR8uwk855KIUs6sZkrHy?=\n\t=?utf-8?q?1i3qhC0kQwV4pZf2460qvYLh1lCoi2f2xC4uwKWNlLBlFSEEt64GdThG8xByTEF7I?=\n\t=?utf-8?q?+GluFJ3x9YI2rgghEhYO85QMZH9vQk6Hx5in87XNxzir2iTr73+76uvQ1zOZXcAni?=\n\t=?utf-8?q?QvMHmhJ6klJxwABRjeiSZaKIWC7E6rLE/oLxZ7FQmh8ECINaUdWDVVMYuaRf0N3rQ?=\n\t=?utf-8?q?lXFyBmAb5Imn1HD03zFDfTlTIFk2aPOdKjmCeVdL/OGWcS2tNMOujkIxCX/ZoIJGm?=\n\t=?utf-8?q?vSZmZopEKth2wbNzizbPVJPEcTv6un6FSQoF10vbxzk7WFLvuUbv0fUlTVasOVc/z?=\n\t=?utf-8?q?kQIzXgLoNJ0TTY8rEbhsZsrSiwjnG70RRHueFQkzXlcyOyrKJ+bIBwYSw2diJ7VGL?=\n\t=?utf-8?q?069jZ23FecBANNhqw5ZE+4oa14kHcMdavNXtTM+bMslR7KJF/I185hLeWThsJzBrr?=\n\t=?utf-8?q?N2PUpH//EjTbghJyWsoGWNEtecIIN1Xt9OKBrJLVP/trJjOtN423ldb8oYt/qjtUD?=\n\t=?utf-8?q?NK88T2KRJfQyKCGEClI1Asb6lJSv05Ku/aKFWv/lEqzbeLLSkXnW+iT50q6D4kys5?=\n\t=?utf-8?q?Kj4iuJjeyQSedkZoD1EM1iFsArQTaEHlqsr5UMVPRFkGkRwrYAOAyWT5LM52CbjUG?=\n\t=?utf-8?q?aIp4hT4O2w8retTab+DRRJ0kVzkKcdjG3J8fWXkqTaZRwZXgj84Wjx0cmkt9iyeOq?=\n\t=?utf-8?q?QeA9+9Ss0ZWvSqyN1JA5wyimn68Q/HEFYklkfZBkBWlsX2qfQuur0rbMBDJW4IvPE?=\n\t=?utf-8?q?v9BkvN15dzn2OWHqeghkdnf0uzGzAZLK1iuk3ohN4AnwGSeRSyTTZTQpoOjtmLIVS?=\n\t=?utf-8?q?ElkWYmMydTxlPXvmM4xx86W0nmLBQJykiq0KbtbHTeZeFN6McQFuMnQqKWhQwK65a?=\n\t=?utf-8?q?1Zhf54RuX7Ve2QQQC9qqoj68OAHDrwpcF/5eEslj1kJZ/pDJPzmqm6RkyWGXaAqkV?=\n\t=?utf-8?q?Oz64QC/n77?=", "X-Forefront-Antispam-Report": "CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:;\n IPV:NLI; SFV:NSPM; H:PUZPR06MB4713.apcprd06.prod.outlook.com; PTR:; CAT:NONE;\n SFS:(13230040)(1800799024)(376014)(52116014)(366016)(38350700014); DIR:OUT;\n SFP:1102;", "X-MS-Exchange-AntiSpam-MessageData-ChunkCount": "1", "X-MS-Exchange-AntiSpam-MessageData-0": "=?utf-8?q?cQMYJ4+uIXplaOihAN2OF+jvPGzK?=\n\t=?utf-8?q?WnnInzuA0/bcHaZVWqwp0D7T+/BtlEMyLILLg/No06Wuqg2zCc4qhtwv4sWGuYhAd?=\n\t=?utf-8?q?hu1mPBbirU9RmUktA4fjQJQZpoJQuY0fcjpw61N9XNs2kXE4+ZgqgUT/beB2m+Ufx?=\n\t=?utf-8?q?3GJlowhlKXfjFCO25h0GJaqrGtZe8ArUwhwXXFbV+GzkSBpPQkaUYHWjK4n2t1BnO?=\n\t=?utf-8?q?Ju3Od0JgjTYMHGh9tV6x+k0quBXB2h7TzAain4ikumGtYLfbpFClqAAa5kE6baJkV?=\n\t=?utf-8?q?5AsDfXSbozzRn3NrnLsIeSlXLOy+JVJEGjGBBGrt6w0Weu+0UaO2AleFBDvPNmU1s?=\n\t=?utf-8?q?ODWB3jrna8KiHxhZhhFxs7sqrqJ7SFpFjE2mqqi4xj5C/DaptClbXuAgoiUDJRYq0?=\n\t=?utf-8?q?p6XLvpJpK8O5n5HSIqd93Zvdt2t3o2UpUkYS8W6dFsLoKlEg4WxekyQUF1msMUtmn?=\n\t=?utf-8?q?ikahsYbE52oyYJ3XbMJ8mCSRfv+YLFpPWAnSsZhVfEidGWzZw760b7JXgaUF1sJcX?=\n\t=?utf-8?q?PZpPHEhzn0wsFXopBggKkODgRS3gFx3bkcS2XZEhp+sWdbkCnQZWETK3Gz1ERcZHZ?=\n\t=?utf-8?q?INc13s3+SNS4wNM6FJ1V5WpRis42uojZubv4rQFW6uS/x9UeW3tsJWw61YbCOiQNE?=\n\t=?utf-8?q?kKDVDtyfc5bHM2dRF6YGEWGZFaF6sSgZSK0cv3+fT5JuKWGbOCa7h2tbI+NzDy1m9?=\n\t=?utf-8?q?8Y+BkJQisJLVGWlTEwDaemEJtwwXIUElR+iIoe2DnZ9XxEzDCWHPEarqHWvQKl72u?=\n\t=?utf-8?q?3aFKhyYIaLX/WBk37FUcMxAZJFug0B1Iz9cHy4Y6l3mhAXZBGzBG/TyzEYkrbUITZ?=\n\t=?utf-8?q?YiW3+nl9arBPx3a6ZoDy+JhtDhXv/4zHEcb98N2r9/pA19Cu21pmZYoCXFGYqlCP5?=\n\t=?utf-8?q?Kbe9i6HFMHlyoo+8ey8rRwYC8gH4mN3aFHUBFsfGjsNHBfAaRAYihOmGaXAoWuUt3?=\n\t=?utf-8?q?qk08Q8boK7Iw8NdeENnpACQyvEAtWT6FJa76Vb7jeriuQkENf1KkBQ1oxkXCd3Wcj?=\n\t=?utf-8?q?Yeya4Q6etxcheo5P1B4UX+YUiTHxl3GegsAOZWgeFeuDcnXbNE1z0aIt2hNCYm4mb?=\n\t=?utf-8?q?nlKdpVrtXzpmh/uUbSl76hv0+Ba4WiVJq5ww3t86n+HxMacJcziY69jeidicQ1VGj?=\n\t=?utf-8?q?d8vJ9e18TPm8kts9jxVl2b7E+viOhFH4yntTmMY0uzPzQFHIuGT6TWnykLtfKV+OB?=\n\t=?utf-8?q?FWvkx8buG7NHARiLGsPdu+UC1Z+x9QbMOhc440TUsJn3Kzi5Gs+YjBTQsmBF8qFf2?=\n\t=?utf-8?q?82osc645PyBEClHzxOg8IvDamqU9uhw1/Ac/WsY/p4EzCWHeiyn/tNJbvJA70j2Hh?=\n\t=?utf-8?q?CBl2SrUNbInnF07Nxa7NlrUDsilNBvDYBY3OXC9qhbff8KjbafoBCErVig8Pg0Zn0?=\n\t=?utf-8?q?mUtk7NbtnhX4jHDyDmgF/OWyIFRdVHY3Sw3n2Y0xDMF2BtzVtuQrNQqvQYZN3dllO?=\n\t=?utf-8?q?rioxU7eKrATZ2JhVX1bWPpIq0BQaUiUwrExn69H82X1HyalL96cCKB/r2kKiwzeca?=\n\t=?utf-8?q?ufOPZP7pYWWq?=", "X-OriginatorOrg": "jaguarmicro.com", "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 5d48c659-627b-4254-17bf-08de3bafd60e", "X-MS-Exchange-CrossTenant-AuthSource": "PUZPR06MB4713.apcprd06.prod.outlook.com", "X-MS-Exchange-CrossTenant-AuthAs": "Internal", "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "15 Dec 2025 07:59:13.1281 (UTC)", "X-MS-Exchange-CrossTenant-FromEntityHeader": "Hosted", "X-MS-Exchange-CrossTenant-Id": "1e45a5c2-d3e1-46b3-a0e6-c5ebf6d8ba7b", "X-MS-Exchange-CrossTenant-MailboxType": "HOSTED", "X-MS-Exchange-CrossTenant-UserPrincipalName": "\n IPdLkClzpRwjk4bjplxt+oyMY7rM1uUswvnuUgPt9uEX51uFY70wPAr6F4wxIir63ittnUKZloS1cRCAUtLNoA==", "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "OSNPR06MB8228", "Received-SPF": "pass client-ip=2a01:111:f403:c406::3;\n envelope-from=wafer@jaguarmicro.com;\n helo=OS8PR02CU002.outbound.protection.outlook.com", "X-Spam_score_int": "-20", "X-Spam_score": "-2.1", "X-Spam_bar": "--", "X-Spam_report": "(-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,\n DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001,\n 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>,\n <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>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>", "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org", "Sender": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org" }, "content": "From: wafer Xie <wafer@jaguarmicro.com>\n\nRetrieve the target buffer from the indirect buffers by index,\nadd the elements sent by the guest into the buffer’s indirect descriptors,\nand update freed_head and freed_number. If freed_number is zero,\nor if the current buffer’s freed_number is less than the number of elements,\nupdate the buffer state to SVQ_INDIRECT_BUF_FREEING.\n\nSigned-off-by: wafer Xie <wafer@jaguarmicro.com>\n---\n hw/virtio/vhost-shadow-virtqueue.c | 245 ++++++++++++++++++++++++++---\n 1 file changed, 224 insertions(+), 21 deletions(-)", "diff": "diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c\nindex 9d43f13842..ef7a1db5ae 100644\n--- a/hw/virtio/vhost-shadow-virtqueue.c\n+++ b/hw/virtio/vhost-shadow-virtqueue.c\n@@ -189,36 +189,237 @@ static bool vhost_svq_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg,\n return true;\n }\n \n-static bool vhost_svq_add_split(VhostShadowVirtqueue *svq,\n+/**\n+ * Write descriptors to indirect descriptor table\n+ *\n+ * @svq: The shadow virtqueue\n+ * @sg: Cache for hwaddr\n+ * @iovec: The iovec from the guest\n+ * @num: iovec length\n+ * @addr: Descriptors' GPAs, if backed by guest memory\n+ * @buf: The indirect descriptor buffer\n+ * @offset_idx: Offset for write position and next field (0 for out, out_num for in)\n+ * @more_descs: True if more descriptors come in the chain\n+ * @write: True if they are writeable descriptors\n+ *\n+ * Return true if success, false otherwise and print error.\n+ */\n+static bool vhost_svq_vring_write_indirect_descs(VhostShadowVirtqueue *svq,\n+ hwaddr *sg,\n+ const struct iovec *iovec,\n+ size_t num,\n+ const hwaddr *addr,\n+ SVQIndirectDescBuf *buf,\n+ size_t offset_idx,\n+ bool more_descs,\n+ bool write)\n+{\n+ bool ok;\n+ uint16_t flags = write ? cpu_to_le16(VRING_DESC_F_WRITE) : 0;\n+ vring_desc_t *descs = buf->desc;\n+ uint16_t i = buf->freed_head + offset_idx;\n+\n+ if (num == 0) {\n+ return true;\n+ }\n+\n+ ok = vhost_svq_translate_addr(svq, sg, iovec, num, addr);\n+ if (unlikely(!ok)) {\n+ return false;\n+ }\n+\n+ for (size_t n = 0; n < num; n++) {\n+ descs[i].addr = cpu_to_le64(sg[n]);\n+ descs[i].len = cpu_to_le32(iovec[n].iov_len);\n+ if (more_descs || (n + 1 < num)) {\n+ descs[i].flags = flags | cpu_to_le16(VRING_DESC_F_NEXT);\n+ descs[i].next = cpu_to_le16(offset_idx + n + 1);\n+ } else {\n+ descs[i].flags = flags;\n+ }\n+ i++;\n+ }\n+\n+ return true;\n+}\n+\n+/**\n+ * Add descriptors to SVQ vring using indirect descriptors (dual-buffer)\n+ *\n+ * @svq: The shadow virtqueue\n+ * @out_sg: The out iovec from the guest\n+ * @out_num: The out iovec length\n+ * @out_addr: The out descriptors' GPAs\n+ * @in_sg: The in iovec from the guest\n+ * @in_num: The in iovec length\n+ * @in_addr: The in descriptors' GPAs\n+ * @sgs: Cache for hwaddr\n+ * @buf_idx: Index of the indirect buffer to use\n+ *\n+ * Return true if success, false otherwise and print error.\n+ */\n+static bool vhost_svq_add_split_indirect(VhostShadowVirtqueue *svq,\n+ const struct iovec *out_sg, size_t out_num,\n+ const hwaddr *out_addr,\n+ const struct iovec *in_sg, size_t in_num,\n+ const hwaddr *in_addr,\n+ hwaddr *sgs, int buf_idx)\n+{\n+ SVQIndirectDescBuf *buf = &svq->indirect_bufs[buf_idx];\n+ uint16_t start_idx = buf->freed_head;\n+ size_t total_descs = out_num + in_num;\n+ hwaddr indirect_iova;\n+ bool ok;\n+\n+ /* Populate indirect descriptor table for out descriptors */\n+ ok = vhost_svq_vring_write_indirect_descs(svq, sgs, out_sg, out_num,\n+ out_addr, buf, 0,\n+ in_num > 0, false);\n+ if (unlikely(!ok)) {\n+ return false;\n+ }\n+\n+ /* Populate indirect descriptor table for in descriptors */\n+ ok = vhost_svq_vring_write_indirect_descs(svq, sgs, in_sg, in_num,\n+ in_addr, buf, out_num,\n+ false, true);\n+ if (unlikely(!ok)) {\n+ return false;\n+ }\n+\n+ /* Calculate IOVA for this indirect descriptor range */\n+ indirect_iova = buf->iova + start_idx * sizeof(vring_desc_t);\n+\n+ /* Add a single descriptor pointing to the indirect table */\n+ svq->vring.desc[svq->free_head].addr = cpu_to_le64(indirect_iova);\n+ svq->vring.desc[svq->free_head].len = cpu_to_le32(total_descs * sizeof(vring_desc_t));\n+ svq->vring.desc[svq->free_head].flags = cpu_to_le16(VRING_DESC_F_INDIRECT);\n+\n+ /* Store indirect descriptor info in desc_state */\n+ svq->desc_state[svq->free_head].indirect_buf_idx = buf_idx;\n+\n+ /* Update buffer state */\n+ buf->freed_head = start_idx + total_descs;\n+ buf->freed_descs -= total_descs;\n+\n+ /* Move free_head forward */\n+ svq->free_head = svq->desc_next[svq->free_head];\n+\n+ return true;\n+}\n+\n+/**\n+ * Try to get a freed indirect buffer for use\n+ *\n+ * @svq: The shadow virtqueue\n+ * @total_descs: Number of descriptors needed\n+ *\n+ * Returns buffer index (0 to SVQ_NUM_INDIRECT_BUFS-1) if available, -1 if none available.\n+ */\n+static int vhost_svq_get_indirect_buf(VhostShadowVirtqueue *svq, size_t total_descs)\n+{\n+ int cur = svq->current_indirect_buf;\n+ SVQIndirectDescBuf *buf;\n+\n+ if (!svq->indirect_enabled) {\n+ return -1;\n+ }\n+\n+ /* Try current buffer first if it's in FREED state */\n+ if (cur >= 0) {\n+ buf = &svq->indirect_bufs[cur];\n+ if (buf->state == SVQ_INDIRECT_BUF_FREED) {\n+ /* Check if we have enough free descriptors */\n+ if (buf->freed_descs >= total_descs) {\n+ return cur;\n+ }\n+ /* Not enough space, switch to FREEING and try next buffer */\n+ buf->state = SVQ_INDIRECT_BUF_FREEING;\n+ }\n+ }\n+\n+ /* Try all other buffers */\n+ for (int i = 0; i < SVQ_NUM_INDIRECT_BUFS; i++) {\n+ if (i == cur) {\n+ continue;\n+ }\n+ buf = &svq->indirect_bufs[i];\n+ if (buf->state == SVQ_INDIRECT_BUF_FREED && buf->freed_descs >= total_descs) {\n+ svq->current_indirect_buf = i;\n+ return i;\n+ }\n+ }\n+\n+ /* All buffers unavailable, fallback to chain mode */\n+ return -1;\n+}\n+\n+static int vhost_svq_add_split(VhostShadowVirtqueue *svq,\n const struct iovec *out_sg, size_t out_num,\n const hwaddr *out_addr,\n const struct iovec *in_sg, size_t in_num,\n- const hwaddr *in_addr, unsigned *head)\n+ const hwaddr *in_addr, unsigned *head,\n+ bool *used_indirect)\n {\n unsigned avail_idx;\n vring_avail_t *avail = svq->vring.avail;\n bool ok;\n g_autofree hwaddr *sgs = g_new(hwaddr, MAX(out_num, in_num));\n+ size_t total_descs = out_num + in_num;\n+ int indirect_buf_idx = -1;\n \n *head = svq->free_head;\n+ *used_indirect = false;\n \n /* We need some descriptors here */\n if (unlikely(!out_num && !in_num)) {\n qemu_log_mask(LOG_GUEST_ERROR,\n \"Guest provided element with no descriptors\");\n- return false;\n+ return -EINVAL;\n }\n \n- ok = vhost_svq_vring_write_descs(svq, sgs, out_sg, out_num, out_addr,\n- in_num > 0, false);\n- if (unlikely(!ok)) {\n- return false;\n+ /* Try to use indirect descriptors if feature is negotiated and total > 1 */\n+ if (virtio_vdev_has_feature(svq->vdev, VIRTIO_RING_F_INDIRECT_DESC) &&\n+ total_descs >= 2) {\n+ indirect_buf_idx = vhost_svq_get_indirect_buf(svq, total_descs);\n }\n \n- ok = vhost_svq_vring_write_descs(svq, sgs, in_sg, in_num, in_addr, false,\n- true);\n- if (unlikely(!ok)) {\n- return false;\n+ if (indirect_buf_idx >= 0) {\n+ /* Indirect mode: only need 1 main descriptor slot */\n+ if (unlikely(vhost_svq_available_slots(svq) < 1)) {\n+ return -ENOSPC;\n+ }\n+\n+ /* Use indirect mode */\n+ ok = vhost_svq_add_split_indirect(svq, out_sg, out_num, out_addr,\n+ in_sg, in_num, in_addr,\n+ sgs, indirect_buf_idx);\n+ if (unlikely(!ok)) {\n+ error_report(\"indirect error, out_num %zu in_num %zu avail index %u head %u\\n\",\n+ out_num, in_num, svq->shadow_avail_idx, *head);\n+ return -EINVAL;\n+ }\n+ *used_indirect = true;\n+ } else {\n+ /* Chain mode: need total_descs descriptor slots */\n+ if (unlikely(vhost_svq_available_slots(svq) < total_descs)) {\n+ return -ENOSPC;\n+ }\n+\n+ /* Use direct (chain) mode */\n+ svq->desc_state[svq->free_head].indirect_buf_idx = -1;\n+\n+ ok = vhost_svq_vring_write_descs(svq, sgs, out_sg, out_num, out_addr,\n+ in_num > 0, false);\n+ if (unlikely(!ok)) {\n+ return -EINVAL;\n+ }\n+\n+ ok = vhost_svq_vring_write_descs(svq, sgs, in_sg, in_num, in_addr, false,\n+ true);\n+ if (unlikely(!ok)) {\n+ return -EINVAL;\n+ }\n }\n \n /*\n@@ -233,7 +434,7 @@ static bool vhost_svq_add_split(VhostShadowVirtqueue *svq,\n smp_wmb();\n avail->idx = cpu_to_le16(svq->shadow_avail_idx);\n \n- return true;\n+ return 0;\n }\n \n static void vhost_svq_kick(VhostShadowVirtqueue *svq)\n@@ -274,19 +475,21 @@ int vhost_svq_add(VhostShadowVirtqueue *svq, const struct iovec *out_sg,\n {\n unsigned qemu_head;\n unsigned ndescs = in_num + out_num;\n- bool ok;\n+ int r;\n+ bool used_indirect = false;\n \n- if (unlikely(ndescs > vhost_svq_available_slots(svq))) {\n- return -ENOSPC;\n+ r = vhost_svq_add_split(svq, out_sg, out_num, out_addr, in_sg, in_num,\n+ in_addr, &qemu_head, &used_indirect);\n+ if (unlikely(r != 0)) {\n+ return r;\n }\n \n- ok = vhost_svq_add_split(svq, out_sg, out_num, out_addr, in_sg, in_num,\n- in_addr, &qemu_head);\n- if (unlikely(!ok)) {\n- return -EINVAL;\n+ /* If using indirect, only 1 main descriptor is used; otherwise ndescs */\n+ if (used_indirect) {\n+ svq->num_free -= 1;\n+ } else {\n+ svq->num_free -= ndescs;\n }\n-\n- svq->num_free -= ndescs;\n svq->desc_state[qemu_head].elem = elem;\n svq->desc_state[qemu_head].ndescs = ndescs;\n vhost_svq_kick(svq);\n", "prefixes": [ "v2", "4/4" ] }