From nobody Sat Sep 26 20:01:29 2026 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=fail(p=none dis=none) header.from=packetfive.com ARC-Seal: i=1; a=rsa-sha256; t=1790116321; cv=none; d=zohomail.com; s=zohoarc; b=Ic4zm+ub4ybNhyirl01oz2lJ15L1+55GeCqWA50pkRPn3hiCUajemzzL+/7MX/ulxoEZcJQ6P2pSHdqwIoJYZHzWJhsjEKlMGaDQVZU8zp5ZyFWvKhL1Od92Le+Xgyye198XP/ZCpF8M0mz2Sl9rMh59xgx4kDZ876wSK/fho6Q= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790116321; 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:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=E/yrKJCjDuZmSSLOO6Exn3E8pLS/glsRsFU41Fc4t+A=; b=KIHNKGyz4TulWqDyw2NPmiND4gQICPJgKv41V+2lU0ocEvyJIy0fXYG3P7aSDs8dSJwd+tmDCeP9vvjwx/s4TadR8K3sBn3KmZZPklKkmEHIy7SVq2lIxxBp6li79TOAkjof7MRgrViVxffo0DBgF/qDao8xMTf7jk+XlKgP1j0= 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=fail header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 179011632100944.05867087886304; Tue, 22 Sep 2026 15:32:01 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x991G-0004Kz-Td; Tue, 22 Sep 2026 18:31:22 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x991D-0004KD-R0 for qemu-devel@nongnu.org; Tue, 22 Sep 2026 18:31:19 -0400 Received: from mail-ed2-x10.google.com ([2a00:1450:4864:33::10]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1x991C-0004Ll-7i for qemu-devel@nongnu.org; Tue, 22 Sep 2026 18:31:19 -0400 Received: by mail-ed2-x10.google.com with SMTP id 4fb4d7f45d1cf-6a99391ffb2so586220a12.0 for ; Tue, 22 Sep 2026 15:31:17 -0700 (PDT) Received: from node-dev.home (86-45-19-184-dynamic.agg1.roc.bbh-prp.eircom.net. [86.45.19.184]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-6aab3883151sm411663a12.14.2026.09.22.15.31.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 22 Sep 2026 15:31:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=packetfive-com.20251104.gappssmtp.com; s=20251104; t=1790116276; x=1790721076; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=E/yrKJCjDuZmSSLOO6Exn3E8pLS/glsRsFU41Fc4t+A=; b=zhCjAtaqcuTB1jGND/9afQCav8sUwXxfZ4lVOhfYFWDOxW2vps9hesNls0JHwREWxj hPV3GJ2EeOBHTOBhokD+UiEXhGn/LCWydZQblBZ3Zvke5SR4X5B/H8jCsVyfCz3+Rfov u+LMLzl72+AtnmDtSwAJxXY/H5YdrS6c+KNQKru6hVOymbFPU0cuklPO5k+4dM2SLIco MKCz/xXalkyWpUaZZTiQgUt7MfrcIUVZHqdD8OPimEEhopv8VlX3z/+b3TMDSE4m9ziG drpHFQBrFuTB2L3sXGety+TZefiXaIpCfiFX7B5zNsiFU9Fz4PCDGpSMESlT83wrsC7Z hoJg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790116276; x=1790721076; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=E/yrKJCjDuZmSSLOO6Exn3E8pLS/glsRsFU41Fc4t+A=; b=1K3nP3pHDiw/VQLtGcynCgGbzbG2gqW5l6zYSUizdrgE2O5ElDFTZx1gHeWRmLrKVG saTWKbjTCQJMZ2Y1c/U4MTbUar6g1ckQU830xLVZGilRMZEYbPsRtA42NvajaKfweqHh VwZrtTh2fbnhidVwS08lVfzQ28ZL1s8OF4SFzOQcf0fHci/spMGJbpDIKIRv63lSsprw vMhWo0Sdxi4Qgr2cICBbILEG8s5jWOoiplKGqVxSVyr6Hv/l+UgUz8moAhxS64O/Gw1H y0AAJccOE8PlX8D+hiTIGlXvxLShv7ZU/H1c4WemKvbZsFXadaSpTTEPdy0wl5G2I6TK dg0A== X-Gm-Message-State: AFuF++kmze0uNR2nk6YBH4EdtWtJo+bhbKuJ0XePPK+Kg3n1zWLpW9w9 9YDPURMTw3d/vHHTywaV5WXjqs6yFg3a+28YnB9epIe4nUYo/ibS+4Pt6n2uBQv31hh/WaKDjmr gNAW7wUI= X-Gm-Gg: AYBFou14H6pAopxgSpcAJCfBw01quhCIDDgilCG+0MHxxfhQQsueGa3J7njEq7O74f0 T2rAeWUS/fHBsAzqmfTJwzKxBedotd2p6aXuM7hA8t2j0Y9MWAaLjj1FoMhJ2+N5JXovvE9zg9t mksdKHfG6Vi4nANOYLRAqI3AEJOUBHHMFeRqvu97Y0FPFU8YNr+lDG3DBXYgC8bFmmxqczofDoP bu4t1OoyVIdXArzGSLdp1TsBgZHz0Vgy2PjXp6vfNhv9ZxOVp2IVM574HXmukHO0g3PnL3XATeK WvR3NvbXdnLZprUpF8nfAVLdwKrJCa5HqZQUUPyMRDX2OZsLRxyrZfI2akwxoh9VLaQO7idu6m1 KFLwUTRMfxWJJ26cUWV4CC+imeANobgkt49E0xOtD/IMjLC+kZX5QCWu8kLvC3n94EKFapOqBOP 4PiNFh6l3MFZwJvh6y7l0o9CW0TSGsd2e6IunNt2x3zABSFVy3f39PRxQKi0Eq4OSCzC7fYRvOI 5N/TmN0K9EoQQsRf3M9VVlat+Bh6UloIWvur4juGypZWPZraTEYxwMq3WB1FxCTZ2A9SjLuGbRv oJ/Zpx6h0yU= X-Received: by 2002:a05:6402:278e:b0:6a7:ee55:dccd with SMTP id 4fb4d7f45d1cf-6aab3b419ddmr563992a12.28.1790116276345; Tue, 22 Sep 2026 15:31:16 -0700 (PDT) From: Weqaar Janjua To: qemu-devel@nongnu.org Cc: kraxel@redhat.com, mst@redhat.com, pierrick.bouvier@oss.qualcomm.com, jasowangio@gmail.com, pbonzini@redhat.com, farosas@suse.de, lvivier@redhat.com Subject: [PATCH v2 1/6] pci: Add device ID for CnuasNIC Date: Tue, 22 Sep 2026 22:30:40 +0000 Message-ID: <20260922223045.190062-2-weqaar.janjua@packetfive.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260922223045.190062-1-weqaar.janjua@packetfive.com> References: <20260922223045.190062-1-weqaar.janjua@packetfive.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=lists1p.gnu.org; Received-SPF: none client-ip=2a00:1450:4864:33::10; envelope-from=weqaar.janjua@packetfive.com; helo=mail-ed2-x10.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_NONE=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 development 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 @packetfive-com.20251104.gappssmtp.com) X-ZM-MESSAGEID: 1790116322261158500 Content-Type: text/plain; charset="utf-8" Reserve device ID 0015 for the Cnuas virtual network adapter. Signed-off-by: Weqaar Janjua --- docs/specs/pci-ids.rst | 2 ++ include/hw/pci/pci.h | 1 + 2 files changed, 3 insertions(+) diff --git a/docs/specs/pci-ids.rst b/docs/specs/pci-ids.rst index 261b0f359f..3f3825bfe5 100644 --- a/docs/specs/pci-ids.rst +++ b/docs/specs/pci-ids.rst @@ -100,6 +100,8 @@ PCI devices (other than virtio): PCI UFS device (``-device ufs``) 1b36:0014 PCI RISC-V IOMMU device +1b36:0015 + Cnuas virtual RDMA network adapter (:doc:`cnuas-vnic`) =20 All these devices are documented in :doc:`index`. =20 diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index f2448e941a..51b3f83514 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -121,6 +121,7 @@ extern bool pci_available; #define PCI_DEVICE_ID_REDHAT_ACPI_ERST 0x0012 #define PCI_DEVICE_ID_REDHAT_UFS 0x0013 #define PCI_DEVICE_ID_REDHAT_RISCV_IOMMU 0x0014 +#define PCI_DEVICE_ID_REDHAT_CNUASNIC 0x0015 #define PCI_DEVICE_ID_REDHAT_QXL 0x0100 =20 #define FMT_PCIBUS PRIx64 --=20 2.43.0 From nobody Sat Sep 26 20:01:29 2026 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=fail(p=none dis=none) header.from=packetfive.com ARC-Seal: i=1; a=rsa-sha256; t=1790116321; cv=none; d=zohomail.com; s=zohoarc; b=HwFjU350rmWk4F7q2UBxzH0W1G6uqYT2O8kjA7IDOYXMTA0CLhzwTfHrlL5ltNOL5PSLajSNxMZpaGvoA+YLGhMqk+qcx/lQE/ZFxZOSF6+S18FbRXxTuY5ERMpKOf587mFUhPo6Ccnh2mUqvfw9Swht7o6Gpeh9Haj0u9ovNnE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790116321; 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:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=tbU8InenrY+vBLNAXnwqAyG5rr4t+l40O8dqkFNIZK0=; b=A7lXUbWBFFiTJzU5jh3b1C5MkobNHfD5QmAWuy5jOCfCQjaJ7cZhukHQqKiuh5yr9Izlvlhq8rVARgKy/LVtUM+bUR2eHPVs3zfHUroH05lt3elDzj/3izanr0Dsgy/QAr0ucE8hJv1LhLuzLaf57n5Hl+pb0A2hwlB0GnzV9us= 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=fail header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1790116321181176.9419051483186; Tue, 22 Sep 2026 15:32:01 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x991S-0004NR-Hl; Tue, 22 Sep 2026 18:31:34 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x991I-0004Lp-Dt for qemu-devel@nongnu.org; Tue, 22 Sep 2026 18:31:24 -0400 Received: from mail-ed2-x0f.google.com ([2a00:1450:4864:33::f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1x991D-0004M7-Vw for qemu-devel@nongnu.org; Tue, 22 Sep 2026 18:31:23 -0400 Received: by mail-ed2-x0f.google.com with SMTP id 4fb4d7f45d1cf-6aa1d00daaaso588483a12.1 for ; Tue, 22 Sep 2026 15:31:19 -0700 (PDT) Received: from node-dev.home (86-45-19-184-dynamic.agg1.roc.bbh-prp.eircom.net. [86.45.19.184]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-6aab3883151sm411663a12.14.2026.09.22.15.31.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 22 Sep 2026 15:31:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=packetfive-com.20251104.gappssmtp.com; s=20251104; t=1790116278; x=1790721078; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=tbU8InenrY+vBLNAXnwqAyG5rr4t+l40O8dqkFNIZK0=; b=oFvDl9iHiW15D1ExRmxv75po+0+saWu7NXeUE67d0VPuk+UKkdWa9Okk7SxtBqnSi7 9oPMOxFwh4qeHDQz4DbCc73PCQ5uAGaKWNESWId6emeATyoK3m8BgxyJylk3U7Osmz3P qXduhr4963+d5Udgh86k6NgjjE+yT4tdVw0L1fmpRF/BIS4olOfpurXMrDsjLKEBmxVS hnq56ber4r6FYR6OYSBBhwXDl9kXi/YvNYkC/7VZEYltiqk0G1JNR41hffrAi99qf2Eg dVpDxi8qzcBeyAfoij9idd8I3gp4sVjaiqr1Cm5aegk+Y9oBASi3ab4MyWcdkRAYZ463 7SrA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790116278; x=1790721078; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=tbU8InenrY+vBLNAXnwqAyG5rr4t+l40O8dqkFNIZK0=; b=JkOj/GDKa/o6m7rWeiDN6rz/AsN3Lvwq99CJ596h/uROTHodUSoXDT+7pxeel7XC8d rnCG/f05p+ZKXSwHH3kK+NTivR5GVr+Wqhb269e0Jz1xQ5IT6/lh/3GedlfCunchYMnB nYxMhfgXiEaHRDW0loXNGDJjjgHAhWSTcJAcYw/8uuhXfPRBli/BXhVLzcngm+JIv/rZ w+4Z0oSFQ5xsLZKc1KKGrD77A/DEHZOYg7sFXJWGMl5OW58f4tvoOlSsfZ5uDz3D+24w iGCsuZaPK0p7zfHku5mue8Ci7P0vP92MRuwZO0+saypXWWdEcbB+AZhIFknmbrE1z1LW MkhQ== X-Gm-Message-State: AFuF++l8R/LIqtgwpPQuBO+90JO/GdMu8rXXfppOIZnLvycaZ8riTHrw dOZjawHiEY40fTFGx6CLUsp6baHhjlyBjbN106A1IpUAcHawPmfrviWOKBkwbrOWYDUMgnKag2m DDDeZPUs= X-Gm-Gg: AYBFou1TblsIhJgjxCeWgnF+MTj6Iw0lF2CtT4FKSsjUD9i0xTrPbke24MU/KB8gMKw owErzABH6J/EhofqbkAx01S4iN8J9/sSFyucZfGxGf9CDW1NWP/xccDGNU9MRR0UFe3Jxrrv5YW kYRN5xjg22EeTpr54J9cGrsK1xzD9yl3WF0up+htLDLRRK2qbXTdptoW6sqEuQqEb2YpBE7Rdcy 9bjfz2L9Z5VO388dbmMB379fCQ2vXb3Z9GIUWFXvLntmNIrOBLZY61HrUI4N+eU8tYnkB4t9ijh eQ7NkXhd6Hypm6LqtIqBGvIuMbjS/62pQJZQlSsJ4m8ivZdEtN0ETM1XfNZ4Ox2+lcOLobgeAf2 sBXwQsK3rQPB0tHq+bc2mFWs1LKbgjaJRYiAUyyajK9Jtjnsp8FzClBH5VozRT5Lk1Cz0JHfHQp S2Jd/5pXO5f8jPFlVOu7+Tcf//27jR6gXBECCfiZFTh1SBlmBuDdgiu18VjP6lVWSln4EIHSrZU umwb3pghTGHLQFmg7bEMIW+UuCnZyRiSdi8wdKyr6qUIRpsLfE9zoXn7fPokBibmdrqPCNFMCx2 X-Received: by 2002:a05:6402:5110:b0:6aa:8d22:a8c3 with SMTP id 4fb4d7f45d1cf-6aab3a795b6mr678237a12.0.1790116278164; Tue, 22 Sep 2026 15:31:18 -0700 (PDT) From: Weqaar Janjua To: qemu-devel@nongnu.org Cc: kraxel@redhat.com, mst@redhat.com, pierrick.bouvier@oss.qualcomm.com, jasowangio@gmail.com, pbonzini@redhat.com, farosas@suse.de, lvivier@redhat.com Subject: [PATCH v2 2/6] hw/net: Add Cnuas virtual network adapter Date: Tue, 22 Sep 2026 22:30:41 +0000 Message-ID: <20260922223045.190062-3-weqaar.janjua@packetfive.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260922223045.190062-1-weqaar.janjua@packetfive.com> References: <20260922223045.190062-1-weqaar.janjua@packetfive.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=lists1p.gnu.org; Received-SPF: none client-ip=2a00:1450:4864:33::f; envelope-from=weqaar.janjua@packetfive.com; helo=mail-ed2-x0f.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, SPF_HELO_NONE=0.001, SPF_NONE=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 development 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 @packetfive-com.20251104.gappssmtp.com) X-ZM-MESSAGEID: 1790116322375158500 Content-Type: text/plain; charset="utf-8" Add guest DMA and packet transport while retaining the existing MIT license. Signed-off-by: Weqaar Janjua --- MAINTAINERS | 6 + docs/specs/cnuas-vnic.rst | 78 ++++++ docs/specs/index.rst | 1 + hw/net/Kconfig | 5 + hw/net/cnuas_vnic.c | 508 ++++++++++++++++++++++++++++++++++++++ hw/net/meson.build | 1 + 6 files changed, 599 insertions(+) create mode 100644 docs/specs/cnuas-vnic.rst create mode 100644 hw/net/cnuas_vnic.c diff --git a/MAINTAINERS b/MAINTAINERS index 6be9c5725b..5f9e8db723 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2772,6 +2772,12 @@ F: net/eth.c F: hw/net/net_rx_pkt* F: hw/net/net_tx_pkt* =20 +Cnuas virtual devices +M: Weqaar Janjua +S: Maintained +F: docs/specs/cnuas-vnic.rst +F: hw/net/cnuas_vnic.c + VMware M: Dmitry Fleytman S: Maintained diff --git a/docs/specs/cnuas-vnic.rst b/docs/specs/cnuas-vnic.rst new file mode 100644 index 0000000000..a8424ad700 --- /dev/null +++ b/docs/specs/cnuas-vnic.rst @@ -0,0 +1,78 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D +Cnuas virtual network adapter +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D + +``cnuas-vnic`` is a PCIe network device for Cnuas RDMA and Ethernet emulat= ion. +Its wire side is an ``AF_UNIX`` ``SOCK_SEQPACKET`` socket, +allowing multiple guests to connect to a separate virtual switch process. +The socket transport currently requires a Linux host. + +The device intentionally uses a single transmit operation and one receive +slot instead of descriptor rings. This keeps the programming model small +while retaining guest DMA, interrupts, link state, and frame transport. + +PCI interface +------------- + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D +Vendor ID 1b36 +Device ID 0015 +Revision 1 +Class 0280, other network controller +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D + +BAR 0 is a 4 KiB MMIO region. The device supports one MSI vector and INTx. + +Properties +---------- + +``socket_path`` + Path of the switch's ``SOCK_SEQPACKET`` socket. Without this property, or + when the connection fails, the device still enumerates with its link dow= n. + +``mac`` + MAC address exposed through ``MAC_LO`` and ``MAC_HI``. If omitted, QEMU + derives a locally administered address from the PCI function number. + +``x-speed``, ``x-width`` + PCIe link speed and width reported through PCIe configuration space. + +Register map +------------ + +All registers require 32-bit little-endian accesses. + +=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +Offset Name Meaning +=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +0x00 TX_ADDR_LO Guest physical transmit address, low 32 bits +0x04 TX_ADDR_HI Guest physical transmit address, high 32 bits +0x08 TX_LEN Frame length from 1 through 9216 bytes +0x0c TX_DOORBELL Write to transmit +0x10 RX_ADDR_LO Guest physical receive address, low 32 bits +0x14 RX_ADDR_HI Guest physical receive address, high 32 bits +0x18 RX_LEN Length of the received frame, read only +0x1c RX_STATUS Bit 0 marks a frame ready; write zero to release +0x20 IRQ_STATUS Interrupt status; write one bits to clear +0x24 IRQ_MASK Interrupt enable mask +0x28 LINK_STATUS Bit 0 marks the socket link up, read only +0x2c MAC_LO MAC bytes 0 through 3, read only +0x30 MAC_HI MAC bytes 4 and 5, read only +=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Interrupt bits are bit 0 for receive completion, bit 1 for transmit +completion, and bit 2 for a link-state change. + +Transport +--------- + +Writing ``TX_DOORBELL`` reads ``TX_LEN`` bytes from guest memory and sends +one socket message. Receive messages are copied to the address in +``RX_ADDR_LO`` and ``RX_ADDR_HI``. The device stops reading its socket whi= le +``RX_STATUS`` is set, preventing a later frame from overwriting the active +receive slot. + +The socket transports complete Ethernet frames without an additional QEMU +header. ``SOCK_SEQPACKET`` preserves frame boundaries. diff --git a/docs/specs/index.rst b/docs/specs/index.rst index 44e108db02..0fd5da2aa8 100644 --- a/docs/specs/index.rst +++ b/docs/specs/index.rst @@ -26,6 +26,7 @@ guest hardware that is specific to QEMU. fw_cfg fsi vmw_pvscsi-spec + cnuas-vnic edu ivshmem-spec pvpanic diff --git a/hw/net/Kconfig b/hw/net/Kconfig index b56a173eed..0721efc8b1 100644 --- a/hw/net/Kconfig +++ b/hw/net/Kconfig @@ -49,6 +49,11 @@ config IGB_PCI_EXPRESS default y if PCI_DEVICES || PCIE_DEVICES depends on PCI_EXPRESS && MSI_NONBROKEN =20 +config CNUAS_VNIC + bool + default y if PCI_DEVICES || PCIE_DEVICES + depends on LINUX && PCI_EXPRESS && MSI_NONBROKEN + config RTL8139_PCI bool default y if PCI_DEVICES diff --git a/hw/net/cnuas_vnic.c b/hw/net/cnuas_vnic.c new file mode 100644 index 0000000000..506d917e39 --- /dev/null +++ b/hw/net/cnuas_vnic.c @@ -0,0 +1,508 @@ +/* + * Cnuas virtual RDMA network adapter + * + * Copyright (c) 2026 PacketFive + * + * SPDX-License-Identifier: MIT + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/main-loop.h" +#include "qemu/module.h" +#include "qemu/units.h" +#include "hw/core/qdev-properties.h" +#include "hw/core/qdev-properties-system.h" +#include "hw/pci/msi.h" +#include "hw/pci/pci.h" +#include "hw/pci/pcie.h" +#include "migration/vmstate.h" +#include "net/net.h" +#include "qapi/error.h" +#include "qom/object.h" + +#include +#include +#include + +#define TYPE_CNUAS_VNIC "cnuas-vnic" +OBJECT_DECLARE_SIMPLE_TYPE(CnuasVnicState, CNUAS_VNIC) + +#define CNUAS_VNIC_MAX_FRAME 9216 +#define CNUAS_VNIC_MMIO_SIZE 4096 + +#define CNUAS_VNIC_REG_TX_ADDR_LO 0x00 +#define CNUAS_VNIC_REG_TX_ADDR_HI 0x04 +#define CNUAS_VNIC_REG_TX_LEN 0x08 +#define CNUAS_VNIC_REG_TX_DOORBELL 0x0c +#define CNUAS_VNIC_REG_RX_ADDR_LO 0x10 +#define CNUAS_VNIC_REG_RX_ADDR_HI 0x14 +#define CNUAS_VNIC_REG_RX_LEN 0x18 +#define CNUAS_VNIC_REG_RX_STATUS 0x1c +#define CNUAS_VNIC_REG_IRQ_STATUS 0x20 +#define CNUAS_VNIC_REG_IRQ_MASK 0x24 +#define CNUAS_VNIC_REG_LINK_STATUS 0x28 +#define CNUAS_VNIC_REG_MAC_LO 0x2c +#define CNUAS_VNIC_REG_MAC_HI 0x30 + +#define CNUAS_VNIC_IRQ_RX_COMPLETE BIT(0) +#define CNUAS_VNIC_IRQ_TX_COMPLETE BIT(1) +#define CNUAS_VNIC_IRQ_LINK_CHANGE BIT(2) + +#define CNUAS_VNIC_LINK_UP BIT(0) +#define CNUAS_VNIC_RX_READY BIT(0) + +struct CnuasVnicState { + PCIDevice parent_obj; + MemoryRegion mmio; + + char *socket_path; + int socket_fd; + + MACAddr conf_mac; + uint8_t mac[6]; + + PCIExpLinkSpeed pcie_speed; + PCIExpLinkWidth pcie_width; + + uint32_t tx_addr_lo; + uint32_t tx_addr_hi; + uint32_t tx_len; + uint32_t rx_addr_lo; + uint32_t rx_addr_hi; + uint32_t rx_len; + uint32_t rx_status; + uint32_t irq_status; + uint32_t irq_mask; + uint32_t link_status; +}; + +static void cnuas_vnic_update_irq(CnuasVnicState *s) +{ + bool pending =3D s->irq_status & s->irq_mask; + + if (msi_enabled(&s->parent_obj)) { + if (pending) { + msi_notify(&s->parent_obj, 0); + } + } else { + pci_set_irq(&s->parent_obj, pending); + } +} + +static void cnuas_vnic_set_link(CnuasVnicState *s, bool up) +{ + uint32_t new_status =3D up ? CNUAS_VNIC_LINK_UP : 0; + + if (s->link_status =3D=3D new_status) { + return; + } + + s->link_status =3D new_status; + s->irq_status |=3D CNUAS_VNIC_IRQ_LINK_CHANGE; + cnuas_vnic_update_irq(s); +} + +static void cnuas_vnic_disconnect(CnuasVnicState *s) +{ + if (s->socket_fd >=3D 0) { + qemu_set_fd_handler(s->socket_fd, NULL, NULL, NULL); + close(s->socket_fd); + s->socket_fd =3D -1; + } + cnuas_vnic_set_link(s, false); +} + +static void cnuas_vnic_transmit(CnuasVnicState *s) +{ + uint8_t frame[CNUAS_VNIC_MAX_FRAME]; + uint64_t address; + ssize_t sent; + + if (!s->tx_len || s->tx_len > sizeof(frame)) { + qemu_log_mask(LOG_GUEST_ERROR, + "cnuas-vnic: invalid TX length %u\n", s->tx_len); + return; + } + + address =3D ((uint64_t)s->tx_addr_hi << 32) | s->tx_addr_lo; + if (pci_dma_read(&s->parent_obj, address, frame, s->tx_len) !=3D MEMTX= _OK) { + qemu_log_mask(LOG_GUEST_ERROR, + "cnuas-vnic: DMA read failed at 0x%" PRIx64 "\n", + address); + return; + } + + if (s->socket_fd >=3D 0 && s->link_status =3D=3D CNUAS_VNIC_LINK_UP) { + sent =3D send(s->socket_fd, frame, s->tx_len, MSG_NOSIGNAL); + if (sent < 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "cnuas-vnic: TX failed: %s\n", strerror(errno)); + if (errno !=3D EAGAIN && errno !=3D EWOULDBLOCK) { + cnuas_vnic_disconnect(s); + } + } else if (sent !=3D s->tx_len) { + qemu_log_mask(LOG_GUEST_ERROR, + "cnuas-vnic: short TX (%zd of %u bytes)\n", + sent, s->tx_len); + } + } + + s->irq_status |=3D CNUAS_VNIC_IRQ_TX_COMPLETE; + cnuas_vnic_update_irq(s); +} + +static bool cnuas_vnic_receive(CnuasVnicState *s) +{ + uint8_t frame[CNUAS_VNIC_MAX_FRAME]; + uint64_t address; + ssize_t length; + + if (s->socket_fd < 0 || s->rx_status =3D=3D CNUAS_VNIC_RX_READY) { + return false; + } + + length =3D recv(s->socket_fd, frame, sizeof(frame), MSG_DONTWAIT); + if (length =3D=3D 0) { + cnuas_vnic_disconnect(s); + return false; + } + if (length < 0) { + if (errno !=3D EAGAIN && errno !=3D EWOULDBLOCK && errno !=3D EINT= R) { + qemu_log_mask(LOG_GUEST_ERROR, + "cnuas-vnic: RX failed: %s\n", strerror(errno)); + cnuas_vnic_disconnect(s); + } + return false; + } + + address =3D ((uint64_t)s->rx_addr_hi << 32) | s->rx_addr_lo; + if (!address) { + qemu_log_mask(LOG_GUEST_ERROR, + "cnuas-vnic: dropped RX frame without a guest buffer= \n"); + return true; + } + + if (pci_dma_write(&s->parent_obj, address, frame, length) !=3D MEMTX_O= K) { + qemu_log_mask(LOG_GUEST_ERROR, + "cnuas-vnic: DMA write failed at 0x%" PRIx64 "\n", + address); + return true; + } + + s->rx_len =3D length; + s->rx_status =3D CNUAS_VNIC_RX_READY; + s->irq_status |=3D CNUAS_VNIC_IRQ_RX_COMPLETE; + cnuas_vnic_update_irq(s); + + /* + * The model has one receive slot. Stop monitoring the level-triggered + * socket until the guest releases that slot to avoid a busy loop. + */ + qemu_set_fd_handler(s->socket_fd, NULL, NULL, NULL); + return true; +} + +static void cnuas_vnic_receive_ready(void *opaque) +{ + cnuas_vnic_receive(opaque); +} + +static uint64_t cnuas_vnic_mmio_read(void *opaque, hwaddr addr, + unsigned size) +{ + CnuasVnicState *s =3D opaque; + + switch (addr) { + case CNUAS_VNIC_REG_TX_ADDR_LO: + return s->tx_addr_lo; + case CNUAS_VNIC_REG_TX_ADDR_HI: + return s->tx_addr_hi; + case CNUAS_VNIC_REG_TX_LEN: + return s->tx_len; + case CNUAS_VNIC_REG_RX_ADDR_LO: + return s->rx_addr_lo; + case CNUAS_VNIC_REG_RX_ADDR_HI: + return s->rx_addr_hi; + case CNUAS_VNIC_REG_RX_LEN: + return s->rx_len; + case CNUAS_VNIC_REG_RX_STATUS: + return s->rx_status; + case CNUAS_VNIC_REG_IRQ_STATUS: + return s->irq_status; + case CNUAS_VNIC_REG_IRQ_MASK: + return s->irq_mask; + case CNUAS_VNIC_REG_LINK_STATUS: + return s->link_status; + case CNUAS_VNIC_REG_MAC_LO: + return s->mac[0] | s->mac[1] << 8 | s->mac[2] << 16 | + s->mac[3] << 24; + case CNUAS_VNIC_REG_MAC_HI: + return s->mac[4] | s->mac[5] << 8; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "cnuas-vnic: read from unknown register 0x%" + HWADDR_PRIx "\n", addr); + return 0; + } +} + +static void cnuas_vnic_mmio_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + CnuasVnicState *s =3D opaque; + + switch (addr) { + case CNUAS_VNIC_REG_TX_ADDR_LO: + s->tx_addr_lo =3D value; + break; + case CNUAS_VNIC_REG_TX_ADDR_HI: + s->tx_addr_hi =3D value; + break; + case CNUAS_VNIC_REG_TX_LEN: + s->tx_len =3D value; + break; + case CNUAS_VNIC_REG_TX_DOORBELL: + cnuas_vnic_transmit(s); + break; + case CNUAS_VNIC_REG_RX_ADDR_LO: + s->rx_addr_lo =3D value; + break; + case CNUAS_VNIC_REG_RX_ADDR_HI: + s->rx_addr_hi =3D value; + break; + case CNUAS_VNIC_REG_RX_STATUS: + if (!value && s->rx_status =3D=3D CNUAS_VNIC_RX_READY) { + s->rx_status =3D 0; + s->rx_len =3D 0; + if (s->socket_fd >=3D 0) { + qemu_set_fd_handler(s->socket_fd, + cnuas_vnic_receive_ready, NULL, s); + cnuas_vnic_receive(s); + } + } + break; + case CNUAS_VNIC_REG_IRQ_STATUS: + s->irq_status &=3D ~value; + cnuas_vnic_update_irq(s); + break; + case CNUAS_VNIC_REG_IRQ_MASK: + s->irq_mask =3D value; + cnuas_vnic_update_irq(s); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "cnuas-vnic: write to unknown register 0x%" + HWADDR_PRIx "\n", addr); + break; + } +} + +static const MemoryRegionOps cnuas_vnic_mmio_ops =3D { + .read =3D cnuas_vnic_mmio_read, + .write =3D cnuas_vnic_mmio_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + }, + .impl =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + }, +}; + +static void cnuas_vnic_connect(CnuasVnicState *s) +{ + struct sockaddr_un address =3D { .sun_family =3D AF_UNIX }; + int flags; + int fd; + int buffer_size =3D 8 * MiB; + + if (!s->socket_path || !s->socket_path[0]) { + return; + } + if (strlen(s->socket_path) >=3D sizeof(address.sun_path)) { + qemu_log_mask(LOG_GUEST_ERROR, + "cnuas-vnic: socket path is too long\n"); + return; + } + + fd =3D socket(AF_UNIX, SOCK_SEQPACKET, 0); + if (fd < 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "cnuas-vnic: socket creation failed: %s\n", + strerror(errno)); + return; + } + + g_strlcpy(address.sun_path, s->socket_path, sizeof(address.sun_path)); + if (connect(fd, (struct sockaddr *)&address, sizeof(address)) < 0) { + qemu_log_mask(LOG_UNIMP, + "cnuas-vnic: cannot connect to %s: %s\n", + s->socket_path, strerror(errno)); + close(fd); + return; + } + + flags =3D fcntl(fd, F_GETFL); + if (flags < 0 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "cnuas-vnic: cannot make socket nonblocking: %s\n", + strerror(errno)); + close(fd); + return; + } + + setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffer_size, sizeof(buffer_size= )); + setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buffer_size, sizeof(buffer_size= )); + + s->socket_fd =3D fd; + cnuas_vnic_set_link(s, true); + qemu_set_fd_handler(fd, cnuas_vnic_receive_ready, NULL, s); +} + +static void cnuas_vnic_reset_hold(Object *obj, ResetType type) +{ + CnuasVnicState *s =3D CNUAS_VNIC(obj); + + s->tx_addr_lo =3D 0; + s->tx_addr_hi =3D 0; + s->tx_len =3D 0; + s->rx_addr_lo =3D 0; + s->rx_addr_hi =3D 0; + s->rx_len =3D 0; + s->rx_status =3D 0; + s->irq_status =3D 0; + s->irq_mask =3D 0; + pci_set_irq(&s->parent_obj, 0); + + if (s->socket_fd >=3D 0) { + qemu_set_fd_handler(s->socket_fd, cnuas_vnic_receive_ready, NULL, = s); + } +} + +static int cnuas_vnic_post_load(void *opaque, int version_id) +{ + CnuasVnicState *s =3D opaque; + + if (s->socket_fd >=3D 0) { + qemu_set_fd_handler(s->socket_fd, + s->rx_status ? NULL : cnuas_vnic_receive_ready, + NULL, s); + } + cnuas_vnic_update_irq(s); + return 0; +} + +static const VMStateDescription vmstate_cnuas_vnic =3D { + .name =3D TYPE_CNUAS_VNIC, + .version_id =3D 1, + .minimum_version_id =3D 1, + .post_load =3D cnuas_vnic_post_load, + .fields =3D (const VMStateField[]) { + VMSTATE_PCI_DEVICE(parent_obj, CnuasVnicState), + VMSTATE_UINT32(tx_addr_lo, CnuasVnicState), + VMSTATE_UINT32(tx_addr_hi, CnuasVnicState), + VMSTATE_UINT32(tx_len, CnuasVnicState), + VMSTATE_UINT32(rx_addr_lo, CnuasVnicState), + VMSTATE_UINT32(rx_addr_hi, CnuasVnicState), + VMSTATE_UINT32(rx_len, CnuasVnicState), + VMSTATE_UINT32(rx_status, CnuasVnicState), + VMSTATE_UINT32(irq_status, CnuasVnicState), + VMSTATE_UINT32(irq_mask, CnuasVnicState), + VMSTATE_END_OF_LIST() + } +}; + +static void cnuas_vnic_realize(PCIDevice *pdev, Error **errp) +{ + CnuasVnicState *s =3D CNUAS_VNIC(pdev); + static const uint8_t zero_mac[6]; + + pci_config_set_interrupt_pin(pdev->config, 1); + if (msi_init(pdev, 0, 1, true, false, errp)) { + return; + } + + if (pcie_endpoint_cap_init(pdev, 0x80) < 0) { + error_setg(errp, "cnuas-vnic: cannot initialize PCIe capability"); + msi_uninit(pdev); + return; + } + pcie_cap_fill_link_ep_usp(pdev, s->pcie_width, s->pcie_speed, false); + + memory_region_init_io(&s->mmio, OBJECT(s), &cnuas_vnic_mmio_ops, s, + "cnuas-vnic-mmio", CNUAS_VNIC_MMIO_SIZE); + pci_register_bar(pdev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio); + + if (!memcmp(s->conf_mac.a, zero_mac, sizeof(zero_mac))) { + s->mac[0] =3D 0x02; + s->mac[1] =3D 0x48; + s->mac[2] =3D 0x43; + s->mac[3] =3D 0x41; + s->mac[4] =3D 0x49; + s->mac[5] =3D pdev->devfn; + } else { + memcpy(s->mac, s->conf_mac.a, sizeof(s->mac)); + } + + s->socket_fd =3D -1; + cnuas_vnic_connect(s); +} + +static void cnuas_vnic_exit(PCIDevice *pdev) +{ + CnuasVnicState *s =3D CNUAS_VNIC(pdev); + + cnuas_vnic_disconnect(s); + pcie_cap_exit(pdev); + msi_uninit(pdev); +} + +static const Property cnuas_vnic_properties[] =3D { + DEFINE_PROP_STRING("socket_path", CnuasVnicState, socket_path), + DEFINE_PROP_MACADDR("mac", CnuasVnicState, conf_mac), + DEFINE_PROP_PCIE_LINK_SPEED("x-speed", CnuasVnicState, pcie_speed, + PCIE_LINK_SPEED_32), + DEFINE_PROP_PCIE_LINK_WIDTH("x-width", CnuasVnicState, pcie_width, + PCIE_LINK_WIDTH_16), +}; + +static void cnuas_vnic_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + PCIDeviceClass *pc =3D PCI_DEVICE_CLASS(klass); + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + + pc->realize =3D cnuas_vnic_realize; + pc->exit =3D cnuas_vnic_exit; + pc->vendor_id =3D PCI_VENDOR_ID_REDHAT; + pc->device_id =3D PCI_DEVICE_ID_REDHAT_CNUASNIC; + pc->class_id =3D PCI_CLASS_NETWORK_OTHER; + pc->revision =3D 1; + + rc->phases.hold =3D cnuas_vnic_reset_hold; + dc->desc =3D "Cnuas virtual RDMA network adapter"; + dc->vmsd =3D &vmstate_cnuas_vnic; + device_class_set_props(dc, cnuas_vnic_properties); + set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); +} + +static const TypeInfo cnuas_vnic_info =3D { + .name =3D TYPE_CNUAS_VNIC, + .parent =3D TYPE_PCI_DEVICE, + .instance_size =3D sizeof(CnuasVnicState), + .class_init =3D cnuas_vnic_class_init, + .interfaces =3D (const InterfaceInfo[]) { + { INTERFACE_PCIE_DEVICE }, + { }, + }, +}; + +static void cnuas_vnic_register_types(void) +{ + type_register_static(&cnuas_vnic_info); +} + +type_init(cnuas_vnic_register_types) diff --git a/hw/net/meson.build b/hw/net/meson.build index 63b0e96245..1b942bd415 100644 --- a/hw/net/meson.build +++ b/hw/net/meson.build @@ -12,6 +12,7 @@ system_ss.add(when: 'CONFIG_E1000E_PCI_EXPRESS', if_true:= files('net_tx_pkt.c', system_ss.add(when: 'CONFIG_E1000E_PCI_EXPRESS', if_true: files('e1000e.c'= , 'e1000e_core.c', 'e1000x_common.c')) system_ss.add(when: 'CONFIG_IGB_PCI_EXPRESS', if_true: files('net_tx_pkt.c= ', 'net_rx_pkt.c')) system_ss.add(when: 'CONFIG_IGB_PCI_EXPRESS', if_true: files('igb.c', 'igb= vf.c', 'igb_core.c')) +system_ss.add(when: 'CONFIG_CNUAS_VNIC', if_true: files('cnuas_vnic.c')) system_ss.add(when: 'CONFIG_RTL8139_PCI', if_true: files('rtl8139.c')) system_ss.add(when: 'CONFIG_TULIP', if_true: files('tulip.c')) system_ss.add(when: 'CONFIG_VMXNET3_PCI', if_true: files('net_tx_pkt.c', '= net_rx_pkt.c')) --=20 2.43.0 From nobody Sat Sep 26 20:01:29 2026 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=fail(p=none dis=none) header.from=packetfive.com ARC-Seal: i=1; a=rsa-sha256; t=1790116363; cv=none; d=zohomail.com; s=zohoarc; b=D9B0BS9DWO0NeGsfWD725eP8I9RPseJx+sac/2iKzdGy7r+wYa2+yyYFBjs49mA4R2KpwimNp8yfQCCJ/2FmZqPpOsGXFnT6OctlagVt4M/KG4QXtothD2L1F/VKBGXC/ubX4BYtwBS9PVpU+6o4V8FNx7W12Pucy+Qn+sD9puA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790116363; 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:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=J7L62qwpJO3vGMxHxjmXF8JdEDxnZEQtw8mo5Q3M2Lc=; b=amSN/lfkp1pgKXjhuKcWyZg1skdPcWopKGfU+LvkDYNkNh/FlATIxskMnpULyqpPAz6yCQP2IYevbIkNyi0BYN+t6NJKm29vySI9SWBNz2SeXEMue/spKpoTlKL7P5EP4vCqVuqhgHNbRhNQg2jemmKhI1MtAiuUOf7S9RCjRVU= 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=fail header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1790116363470643.6121873145187; Tue, 22 Sep 2026 15:32:43 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x991N-0004MW-NG; Tue, 22 Sep 2026 18:31:30 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x991H-0004LN-Dn for qemu-devel@nongnu.org; Tue, 22 Sep 2026 18:31:24 -0400 Received: from mail-ed2-x12.google.com ([2a00:1450:4864:33::12]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1x991F-0004MQ-B4 for qemu-devel@nongnu.org; Tue, 22 Sep 2026 18:31:23 -0400 Received: by mail-ed2-x12.google.com with SMTP id 4fb4d7f45d1cf-6a9984f9a59so560045a12.0 for ; Tue, 22 Sep 2026 15:31:20 -0700 (PDT) Received: from node-dev.home (86-45-19-184-dynamic.agg1.roc.bbh-prp.eircom.net. [86.45.19.184]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-6aab3883151sm411663a12.14.2026.09.22.15.31.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 22 Sep 2026 15:31:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=packetfive-com.20251104.gappssmtp.com; s=20251104; t=1790116280; x=1790721080; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=J7L62qwpJO3vGMxHxjmXF8JdEDxnZEQtw8mo5Q3M2Lc=; b=qiHATVIhvQZa2jt/vq/Iivb2KyrW7RyGo53YoV5RWFF2/ssJy6gHFTEETD4K493/dl iCOEdkjfaK7Nxfx+X7w0OjHtyb1YIxpQ6lgJ+TimFqSoJdQ29GUeDDlxIRosmbc5VP3/ pd16JVNYCbO84IK7xdikmXsiASnKHyTiiB/xHXY5eP5wBdmza9hyhILnBguRI+6H7yQe XV+OJD3UV0BXMPW8FdYHKMfixopwEo5qkayejAln9JvQfT5rzjoFnKzyQ+EOXSWQ3pNN J5vKtMayAdh+mkwdUMtfjF4pNR/ACxabBq+F79W1w4swEK3XLxp6gAOjtivNq8pkd+2C Nn2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790116280; x=1790721080; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=J7L62qwpJO3vGMxHxjmXF8JdEDxnZEQtw8mo5Q3M2Lc=; b=E/yIXWc6OO4WbzG3YPHayET3/45BBcm+TO+ESGzhf/jCDuMX+vWRoioxKlvVYID9AZ J2HSzFvU4BaxsvBuU3i0cspg3qet/p6vJg52X+A+NqnUqaXsjXoN8RmfGWqApudzlFfB QtCWTN/NqvRAcHpHkhtJq/ckcr3dnLN7S9R8eFT2lf8TW7qh4pRDj5F+qkOl/3gaU7ad qDO597TRrZWrAMc2GYi8SCP3hUHhRpZ85L+ALkPbRyVL4Aa7k3Akw9bmbcPS0qAem+Qn 7fkuEST+nmjrN+oqhlxy3TgSnabjWOxSytb/66fTdFPlu1iDuLCezB0lBfFPsGMKPXVm cWog== X-Gm-Message-State: AFuF++k47qczq4C8ID/YBIET2FZu2JIzPxVS0CiSrPU68yt3qGYRF70C ULVchYkBKnbJvQlnmdJQyYIw9N2ZaOBOv37AN5tTZOxgfBZRQs/SCMbjBArE2N49bkFouK7jF7r Aiw1OGkY= X-Gm-Gg: AYBFou2XYdDAB4ZjXZZ8CJOrEqVCHMnoXnYqpN+H+HwTsMrNXUfCpg8GjCDFoNaUtV/ hqbSuJXJ/fIxfgJlgw0ZMoPGF8gxbUnK7xsPi0cOj/pUBzmRfGZKUZQhPAxg1q4uRq5dzHH2ezC iPKqf+0m3HqsGDUdcGebOu+HwrAGtnvXL8L0jqt+P8+Bi9ZkWxFPEd7JnqL3Kw6KfXoWkSJYRUg GmkrCUs92JyzpYTwsQ+cdSazeldgmJWY9pmCc7M6cJKirWJo1I9brSv0R8+5HGm7S+Jczs7Bwhu ibRSMoRQhMz9bOMv33SUWStCJcsGQ+4XT6ljF/EXsKJjdJhjSfLTC8ScrE5Y+6Jk7xwC9JcrNhM IBs6ZcMglFAkr4jxEmzaZtd5O7zaEPb0K78V5/8+GTsO84IB4M13zCNga07VATRXO8MU03WrIDc nomUXtC7d4ELWp1vQ3ailwUn0BczxHB3+mMJVLYEqbz80AIuZbrS0f3+n1yPxacTxDWOEWL30Uv eExkgHRTnj4ISyxsAq4QR2VtH2ltsfswypUzMexz/esNzUGeJkFdTBdyA/LZXtz1Q== X-Received: by 2002:a05:6402:50c8:b0:6a9:b89f:7bb1 with SMTP id 4fb4d7f45d1cf-6aab3b0061emr638781a12.3.1790116279733; Tue, 22 Sep 2026 15:31:19 -0700 (PDT) From: Weqaar Janjua To: qemu-devel@nongnu.org Cc: kraxel@redhat.com, mst@redhat.com, pierrick.bouvier@oss.qualcomm.com, jasowangio@gmail.com, pbonzini@redhat.com, farosas@suse.de, lvivier@redhat.com Subject: [PATCH v2 3/6] tests/qtest: Add Cnuas virtual network adapter tests Date: Tue, 22 Sep 2026 22:30:42 +0000 Message-ID: <20260922223045.190062-4-weqaar.janjua@packetfive.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260922223045.190062-1-weqaar.janjua@packetfive.com> References: <20260922223045.190062-1-weqaar.janjua@packetfive.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=lists1p.gnu.org; Received-SPF: none client-ip=2a00:1450:4864:33::12; envelope-from=weqaar.janjua@packetfive.com; helo=mail-ed2-x12.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, SPF_HELO_NONE=0.001, SPF_NONE=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 development 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 @packetfive-com.20251104.gappssmtp.com) X-ZM-MESSAGEID: 1790116364196158501 Content-Type: text/plain; charset="utf-8" Cover PCI identity, register reset, DMA, and packet transport. Signed-off-by: Weqaar Janjua --- MAINTAINERS | 1 + tests/qtest/cnuas-vnic-test.c | 233 ++++++++++++++++++++++++++++++++++ tests/qtest/meson.build | 1 + 3 files changed, 235 insertions(+) create mode 100644 tests/qtest/cnuas-vnic-test.c diff --git a/MAINTAINERS b/MAINTAINERS index 5f9e8db723..408fc58611 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2777,6 +2777,7 @@ M: Weqaar Janjua S: Maintained F: docs/specs/cnuas-vnic.rst F: hw/net/cnuas_vnic.c +F: tests/qtest/cnuas-vnic-test.c =20 VMware M: Dmitry Fleytman diff --git a/tests/qtest/cnuas-vnic-test.c b/tests/qtest/cnuas-vnic-test.c new file mode 100644 index 0000000000..fc27b7fa8e --- /dev/null +++ b/tests/qtest/cnuas-vnic-test.c @@ -0,0 +1,233 @@ +/* + * QTest for the Cnuas virtual network adapter + * + * Copyright (c) 2026 PacketFive + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "hw/pci/pci.h" +#include "hw/pci/pci_regs.h" +#include "libqos/pci.h" +#include "libqos/pci-pc.h" +#include "libqtest.h" + +#include +#include + +#define CNUAS_VNIC_DEVFN QPCI_DEVFN(4, 0) +#define CNUAS_VNIC_BAR_SIZE 4096 +#define CNUAS_VNIC_REG_TX_ADDR_LO 0x00 +#define CNUAS_VNIC_REG_TX_ADDR_HI 0x04 +#define CNUAS_VNIC_REG_TX_LEN 0x08 +#define CNUAS_VNIC_REG_TX_DOORBELL 0x0c +#define CNUAS_VNIC_REG_RX_ADDR_LO 0x10 +#define CNUAS_VNIC_REG_RX_ADDR_HI 0x14 +#define CNUAS_VNIC_REG_RX_LEN 0x18 +#define CNUAS_VNIC_REG_RX_STATUS 0x1c +#define CNUAS_VNIC_REG_IRQ_STATUS 0x20 +#define CNUAS_VNIC_REG_IRQ_MASK 0x24 +#define CNUAS_VNIC_REG_LINK_STATUS 0x28 +#define CNUAS_VNIC_REG_MAC_LO 0x2c +#define CNUAS_VNIC_REG_MAC_HI 0x30 + +typedef struct CnuasVnicTest { + QTestState *qts; + QPCIBus *bus; + QPCIDevice *dev; + QPCIBar bar; +} CnuasVnicTest; + +static void cnuas_vnic_test_start_with_args(CnuasVnicTest *test, + const char *args) +{ + uint64_t bar_size; + + test->qts =3D qtest_initf("-machine q35 " + "-device cnuas-vnic,addr=3D04.0," + "mac=3D02:11:22:33:44:55%s", args); + test->bus =3D qpci_new_pc(test->qts, NULL); + test->dev =3D qpci_device_find(test->bus, CNUAS_VNIC_DEVFN); + g_assert_nonnull(test->dev); + qpci_device_enable(test->dev); + test->bar =3D qpci_iomap(test->dev, 0, &bar_size); + g_assert_cmpuint(bar_size, =3D=3D, CNUAS_VNIC_BAR_SIZE); +} + +static void cnuas_vnic_test_start(CnuasVnicTest *test) +{ + cnuas_vnic_test_start_with_args(test, ""); +} + +static void cnuas_vnic_test_stop(CnuasVnicTest *test) +{ + g_free(test->dev); + qpci_free_pc(test->bus); + qtest_quit(test->qts); +} + +static void cnuas_vnic_test_pci_config(void) +{ + CnuasVnicTest test; + + cnuas_vnic_test_start(&test); + + g_assert_cmphex(qpci_config_readw(test.dev, PCI_VENDOR_ID), =3D=3D, + PCI_VENDOR_ID_REDHAT); + g_assert_cmphex(qpci_config_readw(test.dev, PCI_DEVICE_ID), =3D=3D, + PCI_DEVICE_ID_REDHAT_CNUASNIC); + g_assert_cmphex(qpci_config_readw(test.dev, PCI_CLASS_DEVICE), =3D=3D, + PCI_CLASS_NETWORK_OTHER); + g_assert_cmphex(qpci_config_readb(test.dev, PCI_REVISION_ID), =3D=3D, = 1); + g_assert_cmphex(qpci_find_capability(test.dev, PCI_CAP_ID_MSI, 0), != =3D, 0); + + cnuas_vnic_test_stop(&test); +} + +static void cnuas_vnic_test_registers(void) +{ + CnuasVnicTest test; + + cnuas_vnic_test_start(&test); + + g_assert_cmphex(qpci_io_readl(test.dev, test.bar, + CNUAS_VNIC_REG_LINK_STATUS), =3D=3D, 0); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar, + CNUAS_VNIC_REG_IRQ_STATUS), =3D=3D, 0); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar, + CNUAS_VNIC_REG_MAC_LO), =3D=3D, 0x332211= 02); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar, + CNUAS_VNIC_REG_MAC_HI), =3D=3D, 0x5544); + + qpci_io_writel(test.dev, test.bar, CNUAS_VNIC_REG_TX_ADDR_LO, + 0x89abcdef); + qpci_io_writel(test.dev, test.bar, CNUAS_VNIC_REG_TX_ADDR_HI, + 0x01234567); + qpci_io_writel(test.dev, test.bar, CNUAS_VNIC_REG_TX_LEN, 4096); + qpci_io_writel(test.dev, test.bar, CNUAS_VNIC_REG_IRQ_MASK, 7); + + g_assert_cmphex(qpci_io_readl(test.dev, test.bar, + CNUAS_VNIC_REG_TX_ADDR_LO), =3D=3D, + 0x89abcdef); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar, + CNUAS_VNIC_REG_TX_ADDR_HI), =3D=3D, + 0x01234567); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar, + CNUAS_VNIC_REG_TX_LEN), =3D=3D, 4096); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar, + CNUAS_VNIC_REG_IRQ_MASK), =3D=3D, 7); + + qtest_system_reset(test.qts); + qpci_device_enable(test.dev); + + g_assert_cmphex(qpci_io_readl(test.dev, test.bar, + CNUAS_VNIC_REG_TX_ADDR_LO), =3D=3D, 0); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar, + CNUAS_VNIC_REG_TX_ADDR_HI), =3D=3D, 0); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar, + CNUAS_VNIC_REG_TX_LEN), =3D=3D, 0); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar, + CNUAS_VNIC_REG_RX_STATUS), =3D=3D, 0); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar, + CNUAS_VNIC_REG_IRQ_MASK), =3D=3D, 0); + + cnuas_vnic_test_stop(&test); +} + +static int cnuas_vnic_test_listen(char **path) +{ + struct sockaddr_un address =3D { .sun_family =3D AF_UNIX }; + int fd; + + *path =3D g_strdup_printf("/tmp/cnuas-vnic-test-%u.sock", getpid()); + unlink(*path); + g_strlcpy(address.sun_path, *path, sizeof(address.sun_path)); + + fd =3D socket(AF_UNIX, SOCK_SEQPACKET, 0); + g_assert_cmpint(fd, >=3D, 0); + g_assert_cmpint(bind(fd, (struct sockaddr *)&address, sizeof(address)), + =3D=3D, 0); + g_assert_cmpint(listen(fd, 1), =3D=3D, 0); + return fd; +} + +static void cnuas_vnic_test_transport(void) +{ + static const uint8_t tx_frame[] =3D { + 0x02, 0, 0, 0, 0, 2, 0x02, 0, 0, 0, 0, 1, 0x08, 0, + 'C', 'n', 'u', 'a', 's', + }; + static const uint8_t rx_frame[] =3D { + 0x02, 0, 0, 0, 0, 1, 0x02, 0, 0, 0, 0, 2, 0x08, 0, + 'R', 'D', 'M', 'A', + }; + uint8_t result[64] =3D { 0 }; + const uint64_t tx_address =3D 0x100000; + const uint64_t rx_address =3D 0x101000; + g_autofree char *path =3D NULL; + g_autofree char *args =3D NULL; + CnuasVnicTest test; + int connection; + int listener; + unsigned int i; + + listener =3D cnuas_vnic_test_listen(&path); + args =3D g_strdup_printf(",socket_path=3D%s", path); + cnuas_vnic_test_start_with_args(&test, args); + connection =3D accept(listener, NULL, NULL); + g_assert_cmpint(connection, >=3D, 0); + + g_assert_cmphex(qpci_io_readl(test.dev, test.bar, + CNUAS_VNIC_REG_LINK_STATUS), =3D=3D, 1); + + qtest_memwrite(test.qts, tx_address, tx_frame, sizeof(tx_frame)); + qpci_io_writel(test.dev, test.bar, CNUAS_VNIC_REG_TX_ADDR_LO, + tx_address); + qpci_io_writel(test.dev, test.bar, CNUAS_VNIC_REG_TX_ADDR_HI, + tx_address >> 32); + qpci_io_writel(test.dev, test.bar, CNUAS_VNIC_REG_TX_LEN, + sizeof(tx_frame)); + qpci_io_writel(test.dev, test.bar, CNUAS_VNIC_REG_TX_DOORBELL, 1); + + g_assert_cmpint(recv(connection, result, sizeof(result), 0), =3D=3D, + sizeof(tx_frame)); + g_assert_cmpmem(result, sizeof(tx_frame), tx_frame, sizeof(tx_frame)); + + qpci_io_writel(test.dev, test.bar, CNUAS_VNIC_REG_RX_ADDR_LO, + rx_address); + qpci_io_writel(test.dev, test.bar, CNUAS_VNIC_REG_RX_ADDR_HI, + rx_address >> 32); + g_assert_cmpint(send(connection, rx_frame, sizeof(rx_frame), 0), =3D= =3D, + sizeof(rx_frame)); + + for (i =3D 0; i < 1000; i++) { + if (qpci_io_readl(test.dev, test.bar, + CNUAS_VNIC_REG_RX_STATUS) =3D=3D 1) { + break; + } + g_usleep(1000); + } + g_assert_cmpuint(i, <, 1000); + g_assert_cmpuint(qpci_io_readl(test.dev, test.bar, + CNUAS_VNIC_REG_RX_LEN), =3D=3D, + sizeof(rx_frame)); + + memset(result, 0, sizeof(result)); + qtest_memread(test.qts, rx_address, result, sizeof(rx_frame)); + g_assert_cmpmem(result, sizeof(rx_frame), rx_frame, sizeof(rx_frame)); + + close(connection); + close(listener); + unlink(path); + cnuas_vnic_test_stop(&test); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + qtest_add_func("/cnuas-vnic/pci-config", cnuas_vnic_test_pci_config); + qtest_add_func("/cnuas-vnic/registers", cnuas_vnic_test_registers); + qtest_add_func("/cnuas-vnic/transport", cnuas_vnic_test_transport); + return g_test_run(); +} diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 33f58b0e95..84d2fa702a 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -59,6 +59,7 @@ qtests_filter =3D \ qtests_i386 =3D \ (slirp.found() ? ['pxe-test'] : []) + \ qtests_filter + \ + (config_all_devices.has_key('CONFIG_CNUAS_VNIC') ? ['cnuas-vnic-test'] := []) + \ (config_all_devices.has_key('CONFIG_ACPI_VMGENID') ? ['vmgenid-test'] : = []) + \ (config_all_devices.has_key('CONFIG_AHCI_ICH9') and have_tools ? ['ahci-= test'] : []) + \ (config_all_devices.has_key('CONFIG_AHCI_ICH9') ? ['tco-test'] : []) + = \ --=20 2.43.0 From nobody Sat Sep 26 20:01:29 2026 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=fail(p=none dis=none) header.from=packetfive.com ARC-Seal: i=1; a=rsa-sha256; t=1790116330; cv=none; d=zohomail.com; s=zohoarc; b=VtSZApUuIiq5n7hrM8M+lATAUEE3+u2THDVUFruOnxrTC7vN4Z92hNg/+iZp0rvmvwyupIWbVEDM78c9/mQHPRqT7h8HJtsVqgtqxn+p1tmnfRwVf71KwdgT2fKkVsp17ifhYa1sWt1xRTNPHtIofhn90zgE9PIVEKok0uMszYU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790116330; 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:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=jPa+3krWwAcEd/vM14z9bDk3/+TaDzZgd+Vvv77ZvNc=; b=gdxJEzBJb3tflrZiU82vbu6zkHuE2pU/FXA+Pf2/SL61A1IEeG4mFUR+EnzKBUixYuxKq8UaGEqHdPnrf2lnzLpekftmbk+U1lGX9VmedrRxGNpL4MaStrmpB2CRY3q122MZZMtBdvUAUgVWYuzYsGYmcRC5uMv5NS96yvIKpxo= 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=fail header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1790116330016436.9766792171283; Tue, 22 Sep 2026 15:32:10 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x991b-0004OT-DP; Tue, 22 Sep 2026 18:31:43 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x991I-0004Lq-JT for qemu-devel@nongnu.org; Tue, 22 Sep 2026 18:31:24 -0400 Received: from mail-ed2-x10.google.com ([2a00:1450:4864:33::10]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1x991G-0004MV-LO for qemu-devel@nongnu.org; Tue, 22 Sep 2026 18:31:24 -0400 Received: by mail-ed2-x10.google.com with SMTP id 4fb4d7f45d1cf-6a99c5de614so451338a12.2 for ; Tue, 22 Sep 2026 15:31:22 -0700 (PDT) Received: from node-dev.home (86-45-19-184-dynamic.agg1.roc.bbh-prp.eircom.net. [86.45.19.184]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-6aab3883151sm411663a12.14.2026.09.22.15.31.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 22 Sep 2026 15:31:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=packetfive-com.20251104.gappssmtp.com; s=20251104; t=1790116281; x=1790721081; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=jPa+3krWwAcEd/vM14z9bDk3/+TaDzZgd+Vvv77ZvNc=; b=fVpOsgoLMJhAbKbf6qGvXmiHcT2Df3XRO1mtrENVaxzk9GtuPow8wBESdGAIy+yAuK eaMzONeHib7wsSgFB2equVhsvXzQuxOEuXHsaxbQqqh/4lWLOEY3LKWkrx02P5VIZaXt vxfHxyjEH8iQf4CAnEmRnTOkn3mVHYokd5EbZOb7ULLP/KAt/eHUOV581Xf4EuQvxbHV TYoqzvkqHZBbuBavsBQnqnDuGEw5GkTzyqMNK6UwtmWk/00UvacvL0cG9UnerpKbJN5U TfazVg+AHhD93uhYGtNnbUIcV2UlRBBL7dPFZzwIvoCuMMxKZcN+OdmRSJWcHXc9h38w bUQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790116281; x=1790721081; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=jPa+3krWwAcEd/vM14z9bDk3/+TaDzZgd+Vvv77ZvNc=; b=cjW5edg5gVLVP2G93EdVHV4FYaKFlORpeAKhvmWSJtpFnJqTVsPn7qoqQbqYAz+HqJ ZRHoi4go8H8n6/S8FWyeOh3BoYc6sMY53BJV0R4YYab1UdBXQmiASN9OhnzXjhYHbGdC HaTUsYIH59KMmIAI0RDzlj1Ai3ymety4RdCkjOttfZeUzBsZwf0yo/y58LknDiJ+t2/V UDLZ75JYePWZrAwZ9dgz4gEekov84r8uXtsvU5Vx2hYwAmGH99lgj+zvaPhlzFPoKjNr Gj9QNTBz7VPabsctVZV1LemC8iLlRL0wYGBwzP0Ey2yzQ6M3GOerO7CVpvXGXVn2K9tt V+7Q== X-Gm-Message-State: AFuF++leAW4SPN5QQSIf48uQpfnos/HsZPIS0/McC3Xx9ww/UcwNNkLG 0WJInHLTq0PCAGtPtWYYUUXc8y2pOFq/fcrkqgHeQYBIYsPtiRIsH2+simeO3HDk03R1rRanZoa H4v4YeK0= X-Gm-Gg: AYBFou0+1SkR92ylD6I3Kmcxij8KnnzG8Btak5ksqW6S4Qx454qd2oiuD6nh6DeQ2d+ cH0QTOhk4o+b06SPDf0vO46lfJix35ybw0zseghXjS1qN/yPsdCT6se3iJ6t5Cj6m/OZ1dROQW0 v1xKPAY3A0eTCfiwzXcen8aVofwVyZwiTY3w5NM9eikgbbBYehb0qT9SSiZGr17iCWJF9s8BIO/ lEM3sMi9Jz/dTGV/Tz3GPPMqnIUsaA/Qiqb/9r5dctafcmx1CQMNqsSK3lIUJxcf9G0E0fNEig4 Qw1tXTEc1hV9dA26yAa9RkVEvXUx1JhXLYyjyCEJnTjcrNdTL67pXDsb+QWOUg9cFLa0MBHVx3d r1bk6UMwlszsow/ZsN5ik/14Epi3aU+sB3JJ84WeqTTnBdGkCn6gWhK+Jua/PNJG2HovBN17XFp NySeIBfW5hRhyluIQicvdzwUG5DfQKiKBjalukm9kF6R5c8djhb6cSRzTecX3BJ/M8ju5ZA1JlK x+o9ZzPP8QJFekwTkUgzuMQXyDLYPokTkY0SlTnPkb2OAacZWml8Dn7Lf2yA1ZymhILKguCubT8 X-Received: by 2002:a05:6402:52c5:b0:6a9:d0f0:69a0 with SMTP id 4fb4d7f45d1cf-6aab3b0a3e2mr560926a12.11.1790116281332; Tue, 22 Sep 2026 15:31:21 -0700 (PDT) From: Weqaar Janjua To: qemu-devel@nongnu.org Cc: kraxel@redhat.com, mst@redhat.com, pierrick.bouvier@oss.qualcomm.com, jasowangio@gmail.com, pbonzini@redhat.com, farosas@suse.de, lvivier@redhat.com Subject: [PATCH v2 4/6] pci: Add device ID for CnuasGPU Date: Tue, 22 Sep 2026 22:30:43 +0000 Message-ID: <20260922223045.190062-5-weqaar.janjua@packetfive.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260922223045.190062-1-weqaar.janjua@packetfive.com> References: <20260922223045.190062-1-weqaar.janjua@packetfive.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=lists1p.gnu.org; Received-SPF: none client-ip=2a00:1450:4864:33::10; envelope-from=weqaar.janjua@packetfive.com; helo=mail-ed2-x10.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_NONE=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 development 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 @packetfive-com.20251104.gappssmtp.com) X-ZM-MESSAGEID: 1790116332016158501 Content-Type: text/plain; charset="utf-8" Reserve device ID 0016 for the CnuasGPU virtual accelerator. Signed-off-by: Weqaar Janjua --- docs/specs/pci-ids.rst | 2 ++ include/hw/pci/pci.h | 1 + 2 files changed, 3 insertions(+) diff --git a/docs/specs/pci-ids.rst b/docs/specs/pci-ids.rst index 3f3825bfe5..bda59c20cb 100644 --- a/docs/specs/pci-ids.rst +++ b/docs/specs/pci-ids.rst @@ -102,6 +102,8 @@ PCI devices (other than virtio): PCI RISC-V IOMMU device 1b36:0015 Cnuas virtual RDMA network adapter (:doc:`cnuas-vnic`) +1b36:0016 + CnuasGPU virtual accelerator (:doc:`cnuasgpu`) =20 All these devices are documented in :doc:`index`. =20 diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 51b3f83514..ad74f5456e 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -122,6 +122,7 @@ extern bool pci_available; #define PCI_DEVICE_ID_REDHAT_UFS 0x0013 #define PCI_DEVICE_ID_REDHAT_RISCV_IOMMU 0x0014 #define PCI_DEVICE_ID_REDHAT_CNUASNIC 0x0015 +#define PCI_DEVICE_ID_REDHAT_CNUASGPU 0x0016 #define PCI_DEVICE_ID_REDHAT_QXL 0x0100 =20 #define FMT_PCIBUS PRIx64 --=20 2.43.0 From nobody Sat Sep 26 20:01:29 2026 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=fail(p=none dis=none) header.from=packetfive.com ARC-Seal: i=1; a=rsa-sha256; t=1790116355; cv=none; d=zohomail.com; s=zohoarc; b=coyr4JQoKxeqbLPGfw/6F3BSm8Y5XD3woQweNwhI+PEY2Wumj3dHu8zWsSMcJZtdDtn+5bR32WqRP5g3IteZP4O5ie3hJ+5sIR9Di/0Tp/Z225h8dTvXu+HYn3PfxnduSwPTh1NDMfG9FYwDOKP0Z4UHAwQ2Qpdol4J3IFV8uAs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790116355; 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:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=5Jz6crVFq/N77QW3ICnfGdhCdnADH4+4jelXJLVMzzk=; b=G9mQHFXBP1tT3tkO1gkch8PRmhduL4PuZcuPoEhnN5oLRNReH3fZyEBSpY6xAR6e/5TJ9TlWBRVBTn1sYY/kfZy0pw5ewR0CeiDS/rCQUvkDNkWSp8VM85G0wIeMnhRrDzK8OMzOZTDyvWtaXNAHuG7LoG1SNgOBPy3sCpxZ3c4= 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=fail header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1790116355128566.0286734277612; Tue, 22 Sep 2026 15:32:35 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x991c-0004Pj-9Q; Tue, 22 Sep 2026 18:31:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x991L-0004MU-2E for qemu-devel@nongnu.org; Tue, 22 Sep 2026 18:31:28 -0400 Received: from mail-ed2-x10.google.com ([2a00:1450:4864:33::10]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1x991I-0004Md-6N for qemu-devel@nongnu.org; Tue, 22 Sep 2026 18:31:26 -0400 Received: by mail-ed2-x10.google.com with SMTP id 4fb4d7f45d1cf-6a605c198fdso520832a12.2 for ; Tue, 22 Sep 2026 15:31:23 -0700 (PDT) Received: from node-dev.home (86-45-19-184-dynamic.agg1.roc.bbh-prp.eircom.net. [86.45.19.184]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-6aab3883151sm411663a12.14.2026.09.22.15.31.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 22 Sep 2026 15:31:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=packetfive-com.20251104.gappssmtp.com; s=20251104; t=1790116283; x=1790721083; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=5Jz6crVFq/N77QW3ICnfGdhCdnADH4+4jelXJLVMzzk=; b=oetUoC2Khrt9Bxd/jieiJ+mL0j6Xz1HOxYDcl1LkyVQOd/7CS+eI3UQEWG3ZKSjUTY SoQ+8iuyvNC3ksGw8woLMbkIut3VuldI/rBsmeXjSWXFMClMUrisVa4gKv7TDrnSD1As aN+uyxaw3YN4u5EJG2ZyKGXd5hCKT8kF/oIdZ3+/4nFt/hFcixwZScmn+Bz2AYj1ki3d bdBogxuevZAYo8rmBFbGpxZmg9bro8mqHcWAeX7mdRaW+Zbw3RZBls1/i4PmQiNMxqrl JCNE3mj/HVM3kbRQONY2OC0G/nwH0Gs/PhGIp77Ch2yByIelLPOvppAra0ZxRt78YfXb dpBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790116283; x=1790721083; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=5Jz6crVFq/N77QW3ICnfGdhCdnADH4+4jelXJLVMzzk=; b=jCxoNZxS/lFrYzDC+qcVZrAfHYWWo8Xy4FgrZY3V7w+4DYQohf9FNSlA7THNoCI4G1 pMooQOEg4wgwdu2OrzH/hg4UUqErmnDqJL9wmNGXC/abk0ETJSveKh4gaSRZrmxk8ZHC 2GD5nSMThXRrI/0jQSTr985ihr4BzZp2QypkWmeHPj4OQozJVMTKeLGeWzHk7v6HSWbd PIajvrQCTTjvdlvECLXf7XCxnRKTGSb/BeC5DYBe9E0BC29dLO/J0BQBrAA3E/0MgkCQ j9GkWyzh+R57lNbANpwTvK32OZWvzNMOVeTKNDlglD3XqSXavBIB+orq1CBzdoAw/58+ lqJg== X-Gm-Message-State: AFuF++kOnJS97/xRr7TLflKbFkFW/nZFqgARC7hlD2cpjH5VDIbUti4q ++lm9ijjiUsoDbEN0+Lmuxz7GyFeOAxVI6hY1Xa3XTIxPfk0hNYer0TL4PEmM9+g3uBHMQSnR9t hpQVc1yw= X-Gm-Gg: AYBFou3jugAghvnTSqFIkMu6Cz5xx5J2gSy86xxZaKNR6PemVUI/HUGylxbtplxBQ89 UQmRoke3lhWyhqPMIM9JPKU9iGCATLHPV1BR4Evf2Dtlp/H0EHzPjRJDp3lsMFkDRYJnBP9idRS a4uIbFX6D8dUstlaKhaUWah+Kl1jsRkmwR7TnBT715/IwlJ5zaF/lsxF2ShEm1F3vJPIh1wU+Tb +JaRzzR/QEwXJJuBqAwfHVq/oagcy59w1pGw9iDffY0Loe/tNq9eb5ogIqRqLfpyp/yUmvfKRWj x/KZxlthhHv/HHFkGMwzB5ikZHbec3d5yR6Vps5LM5pWoh/DZF5Z9PqyTGBq55uZxg4aZNPsu1n qoxQ4BpMlMTcd1dzZXG+7JtjuOXMPIh9kjVu2ruSPG6iB2V+zVBfx/f+X5OuRj/cNb56Vy4Ay3U 6Gafl+IKdBd2NUkDvrgc4wMW+7wUeyrmJdIWfIaJvY/8RfpSwbMJr/ArXSwkU8ANCF8UMDC1lhs oikt7QMFQyX95visUjn0lbtbMAhKFQHH9t8kHo83GqqjakcvHWpGjyHqJCgKRqCh2vtUC98RKh2 X-Received: by 2002:a05:6402:274c:b0:6a9:dc6a:689c with SMTP id 4fb4d7f45d1cf-6aab3b56a43mr599522a12.22.1790116282181; Tue, 22 Sep 2026 15:31:22 -0700 (PDT) From: Weqaar Janjua To: qemu-devel@nongnu.org Cc: kraxel@redhat.com, mst@redhat.com, pierrick.bouvier@oss.qualcomm.com, jasowangio@gmail.com, pbonzini@redhat.com, farosas@suse.de, lvivier@redhat.com Subject: [PATCH v2 5/6] hw/misc: Add CnuasGPU virtual accelerator Date: Tue, 22 Sep 2026 22:30:44 +0000 Message-ID: <20260922223045.190062-6-weqaar.janjua@packetfive.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260922223045.190062-1-weqaar.janjua@packetfive.com> References: <20260922223045.190062-1-weqaar.janjua@packetfive.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=lists1p.gnu.org; Received-SPF: none client-ip=2a00:1450:4864:33::10; envelope-from=weqaar.janjua@packetfive.com; helo=mail-ed2-x10.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_NONE=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 development 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 @packetfive-com.20251104.gappssmtp.com) X-ZM-MESSAGEID: 1790116356308158500 Content-Type: text/plain; charset="utf-8" Add device memory, interrupt state, and link transport. Signed-off-by: Weqaar Janjua --- MAINTAINERS | 2 + docs/specs/cnuasgpu.rst | 91 +++++++ docs/specs/index.rst | 1 + hw/misc/Kconfig | 5 + hw/misc/cnuasgpu.c | 557 ++++++++++++++++++++++++++++++++++++++++ hw/misc/meson.build | 1 + 6 files changed, 657 insertions(+) create mode 100644 docs/specs/cnuasgpu.rst create mode 100644 hw/misc/cnuasgpu.c diff --git a/MAINTAINERS b/MAINTAINERS index 408fc58611..d11ea29ff9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2776,6 +2776,8 @@ Cnuas virtual devices M: Weqaar Janjua S: Maintained F: docs/specs/cnuas-vnic.rst +F: docs/specs/cnuasgpu.rst +F: hw/misc/cnuasgpu.c F: hw/net/cnuas_vnic.c F: tests/qtest/cnuas-vnic-test.c =20 diff --git a/docs/specs/cnuasgpu.rst b/docs/specs/cnuasgpu.rst new file mode 100644 index 0000000000..8c8241b505 --- /dev/null +++ b/docs/specs/cnuasgpu.rst @@ -0,0 +1,91 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D +CnuasGPU virtual accelerator +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D + +``cnuasgpu`` is the PCIe device model for the Cnuas virtual AI/ML +accelerator. It emulates the guest-visible control, device-memory, interru= pt, +and peer-fabric interfaces. Compute kernels are executed by Cnuas runtime +backends rather than by a cycle-accurate GPU pipeline inside QEMU. Its +optional ``SOCK_SEQPACKET`` transport currently requires a Linux host. + +PCI interface +------------- + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +Vendor ID 1b36 +Device ID 0016 +Revision 1 +Class 0b40, co-processor +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +BAR Contents +=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +0 64 KiB MMIO register region +1 64-bit prefetchable device memory, 256 MiB by default +=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +The device supports one MSI vector and INTx. + +Properties +---------- + +``gpu_id`` + Guest-visible accelerator identifier. + +``sm_count``, ``lanes_per_sm``, ``tensor_size`` + Guest-visible geometry values. They do not control a compute engine. + +``devmem_size`` + BAR 1 size. It must be a power of two from 16 MiB through 1 TiB. + +``cnuaslink_socket`` + Optional ``AF_UNIX`` ``SOCK_SEQPACKET`` endpoint for CnuasLink frames. + +``x-speed``, ``x-width`` + PCIe link speed and width reported through PCIe configuration space. + +Register map +------------ + +All registers require 32-bit little-endian accesses. + +=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +Offset Name Meaning +=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +0x000 VENDOR_ID 0x1b36, read only +0x004 DEVICE_ID 0x0016, read only +0x008 REVISION 0x01, read only +0x00c FW_VERSION 0x00010000, read only +0x010 GPU_ID ``gpu_id`` property, read only +0x014 SM_COUNT ``sm_count`` property, read only +0x018 LANES_PER_SM ``lanes_per_sm`` property, read only +0x01c TENSOR_SIZE ``tensor_size`` property, read only +0x020 DEVMEM_SIZE_LO BAR 1 size, low 32 bits, read only +0x024 DEVMEM_SIZE_HI BAR 1 size, high 32 bits, read only +0x100 IRQ_STATUS Interrupt status; write one bits to clear +0x104 IRQ_MASK Interrupt enable mask +0x200 LINK_STATUS Bit 0 link up, bit 1 receive ready +0x204 TX_OFFSET_LO BAR 1 transmit offset, low 32 bits +0x208 TX_OFFSET_HI BAR 1 transmit offset, high 32 bits +0x20c TX_LEN Transmit length from 1 through 65536 bytes +0x210 TX_DOORBELL Write nonzero to transmit +0x214 RX_OFFSET_LO BAR 1 receive offset, low 32 bits +0x218 RX_OFFSET_HI BAR 1 receive offset, high 32 bits +0x21c RX_BUF_SIZE Maximum accepted receive length +0x220 RX_LEN Last receive length, read only +0x224 RX_CONSUME Write nonzero to release the receive buffer +=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Interrupt bit 0 reports transmit completion and bit 1 reports an available +receive frame. + +CnuasLink +--------- + +The optional socket transports one frame per message. A transmit reads from +BAR 1. A receive writes to BAR 1 and pauses socket monitoring until the gu= est +writes ``RX_CONSUME``. Offsets and lengths are checked against BAR 1 before +the model accesses device memory. diff --git a/docs/specs/index.rst b/docs/specs/index.rst index 0fd5da2aa8..e674d76da6 100644 --- a/docs/specs/index.rst +++ b/docs/specs/index.rst @@ -27,6 +27,7 @@ guest hardware that is specific to QEMU. fsi vmw_pvscsi-spec cnuas-vnic + cnuasgpu edu ivshmem-spec pvpanic diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index 46e3c03cc8..39d52674e0 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -35,6 +35,11 @@ config EDU default y if TEST_DEVICES depends on PCI && MSI_NONBROKEN =20 +config CNUAS_GPU + bool + default y if PCI_DEVICES || PCIE_DEVICES + depends on LINUX && PCI_EXPRESS && MSI_NONBROKEN + config I2C_ECHO bool default y if TEST_DEVICES diff --git a/hw/misc/cnuasgpu.c b/hw/misc/cnuasgpu.c new file mode 100644 index 0000000000..38ac1bdb42 --- /dev/null +++ b/hw/misc/cnuasgpu.c @@ -0,0 +1,557 @@ +/* + * CnuasGPU virtual accelerator + * + * Copyright (c) 2026 PacketFive + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/main-loop.h" +#include "qemu/module.h" +#include "qemu/units.h" +#include "hw/core/qdev-properties.h" +#include "hw/core/qdev-properties-system.h" +#include "hw/pci/msi.h" +#include "hw/pci/pci.h" +#include "hw/pci/pcie.h" +#include "migration/vmstate.h" +#include "qapi/error.h" +#include "qom/object.h" + +#include +#include +#include + +#define TYPE_CNUAS_GPU "cnuasgpu" +OBJECT_DECLARE_SIMPLE_TYPE(CnuasGpuState, CNUAS_GPU) + +#define CNUAS_GPU_BAR0_SIZE (64 * KiB) +#define CNUAS_GPU_DEVMEM_DEFAULT (256 * MiB) +#define CNUAS_GPU_DEVMEM_MIN (16 * MiB) +#define CNUAS_GPU_DEVMEM_MAX (1024ULL * GiB) +#define CNUAS_GPU_LINK_MAX_FRAME (64 * KiB) + +#define CNUAS_GPU_REG_VENDOR_ID 0x000 +#define CNUAS_GPU_REG_DEVICE_ID 0x004 +#define CNUAS_GPU_REG_REVISION 0x008 +#define CNUAS_GPU_REG_FW_VERSION 0x00c +#define CNUAS_GPU_REG_GPU_ID 0x010 +#define CNUAS_GPU_REG_SM_COUNT 0x014 +#define CNUAS_GPU_REG_LANES_PER_SM 0x018 +#define CNUAS_GPU_REG_TENSOR_SIZE 0x01c +#define CNUAS_GPU_REG_DEVMEM_SIZE_LO 0x020 +#define CNUAS_GPU_REG_DEVMEM_SIZE_HI 0x024 +#define CNUAS_GPU_REG_IRQ_STATUS 0x100 +#define CNUAS_GPU_REG_IRQ_MASK 0x104 +#define CNUAS_GPU_REG_LINK_STATUS 0x200 +#define CNUAS_GPU_REG_TX_OFFSET_LO 0x204 +#define CNUAS_GPU_REG_TX_OFFSET_HI 0x208 +#define CNUAS_GPU_REG_TX_LEN 0x20c +#define CNUAS_GPU_REG_TX_DOORBELL 0x210 +#define CNUAS_GPU_REG_RX_OFFSET_LO 0x214 +#define CNUAS_GPU_REG_RX_OFFSET_HI 0x218 +#define CNUAS_GPU_REG_RX_BUF_SIZE 0x21c +#define CNUAS_GPU_REG_RX_LEN 0x220 +#define CNUAS_GPU_REG_RX_CONSUME 0x224 + +#define CNUAS_GPU_FW_VERSION 0x00010000 +#define CNUAS_GPU_REVISION 1 + +#define CNUAS_GPU_IRQ_TX_DONE BIT(0) +#define CNUAS_GPU_IRQ_RX_AVAILABLE BIT(1) + +#define CNUAS_GPU_LINK_UP BIT(0) +#define CNUAS_GPU_LINK_RX_READY BIT(1) + +struct CnuasGpuState { + PCIDevice parent_obj; + MemoryRegion bar0; + MemoryRegion bar1; + + uint32_t gpu_id; + uint32_t sm_count; + uint32_t lanes_per_sm; + uint32_t tensor_size; + uint64_t devmem_size; + PCIExpLinkSpeed pcie_speed; + PCIExpLinkWidth pcie_width; + + uint32_t irq_status; + uint32_t irq_mask; + + char *link_socket; + int socket_fd; + bool link_up; + uint32_t tx_offset_lo; + uint32_t tx_offset_hi; + uint32_t tx_len; + uint32_t rx_offset_lo; + uint32_t rx_offset_hi; + uint32_t rx_buf_size; + uint32_t rx_len; + bool rx_ready; +}; + +static void cnuas_gpu_update_irq(CnuasGpuState *s) +{ + bool pending =3D s->irq_status & s->irq_mask; + + if (msi_enabled(&s->parent_obj)) { + if (pending) { + msi_notify(&s->parent_obj, 0); + } + } else { + pci_set_irq(&s->parent_obj, pending); + } +} + +static void *cnuas_gpu_devmem_ptr(CnuasGpuState *s, uint64_t offset, + size_t length) +{ + if (offset > s->devmem_size || length > s->devmem_size - offset) { + return NULL; + } + + return memory_region_get_ram_ptr(&s->bar1) + offset; +} + +static void cnuas_gpu_disconnect(CnuasGpuState *s) +{ + if (s->socket_fd >=3D 0) { + qemu_set_fd_handler(s->socket_fd, NULL, NULL, NULL); + close(s->socket_fd); + s->socket_fd =3D -1; + } + s->link_up =3D false; + s->rx_ready =3D false; + s->rx_len =3D 0; +} + +static void cnuas_gpu_receive_ready(void *opaque) +{ + CnuasGpuState *s =3D opaque; + uint8_t frame[CNUAS_GPU_LINK_MAX_FRAME]; + uint64_t offset; + void *destination; + ssize_t length; + + if (s->rx_ready) { + qemu_set_fd_handler(s->socket_fd, NULL, NULL, NULL); + return; + } + + length =3D recv(s->socket_fd, frame, sizeof(frame), MSG_DONTWAIT); + if (length =3D=3D 0) { + cnuas_gpu_disconnect(s); + return; + } + if (length < 0) { + if (errno !=3D EAGAIN && errno !=3D EWOULDBLOCK && errno !=3D EINT= R) { + qemu_log_mask(LOG_GUEST_ERROR, + "cnuasgpu: link receive failed: %s\n", + strerror(errno)); + cnuas_gpu_disconnect(s); + } + return; + } + + if (!s->rx_buf_size || length > s->rx_buf_size) { + qemu_log_mask(LOG_GUEST_ERROR, + "cnuasgpu: RX frame does not fit guest buffer\n"); + return; + } + + offset =3D ((uint64_t)s->rx_offset_hi << 32) | s->rx_offset_lo; + destination =3D cnuas_gpu_devmem_ptr(s, offset, length); + if (!destination) { + qemu_log_mask(LOG_GUEST_ERROR, + "cnuasgpu: RX range exceeds device memory\n"); + return; + } + + memcpy(destination, frame, length); + s->rx_len =3D length; + s->rx_ready =3D true; + s->irq_status |=3D CNUAS_GPU_IRQ_RX_AVAILABLE; + cnuas_gpu_update_irq(s); + qemu_set_fd_handler(s->socket_fd, NULL, NULL, NULL); +} + +static void cnuas_gpu_connect(CnuasGpuState *s) +{ + struct sockaddr_un address =3D { .sun_family =3D AF_UNIX }; + int flags; + int fd; + + if (!s->link_socket || !s->link_socket[0]) { + return; + } + if (strlen(s->link_socket) >=3D sizeof(address.sun_path)) { + qemu_log_mask(LOG_GUEST_ERROR, + "cnuasgpu: link socket path is too long\n"); + return; + } + + fd =3D socket(AF_UNIX, SOCK_SEQPACKET, 0); + if (fd < 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "cnuasgpu: link socket creation failed: %s\n", + strerror(errno)); + return; + } + + g_strlcpy(address.sun_path, s->link_socket, sizeof(address.sun_path)); + if (connect(fd, (struct sockaddr *)&address, sizeof(address)) < 0) { + qemu_log_mask(LOG_UNIMP, + "cnuasgpu: cannot connect to %s: %s\n", + s->link_socket, strerror(errno)); + close(fd); + return; + } + + flags =3D fcntl(fd, F_GETFL); + if (flags < 0 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "cnuasgpu: cannot make socket nonblocking: %s\n", + strerror(errno)); + close(fd); + return; + } + + s->socket_fd =3D fd; + s->link_up =3D true; + qemu_set_fd_handler(fd, cnuas_gpu_receive_ready, NULL, s); +} + +static void cnuas_gpu_transmit(CnuasGpuState *s) +{ + uint64_t offset; + void *source; + ssize_t sent; + + if (!s->link_up || s->socket_fd < 0) { + return; + } + if (!s->tx_len || s->tx_len > CNUAS_GPU_LINK_MAX_FRAME) { + qemu_log_mask(LOG_GUEST_ERROR, + "cnuasgpu: invalid TX length %u\n", s->tx_len); + return; + } + + offset =3D ((uint64_t)s->tx_offset_hi << 32) | s->tx_offset_lo; + source =3D cnuas_gpu_devmem_ptr(s, offset, s->tx_len); + if (!source) { + qemu_log_mask(LOG_GUEST_ERROR, + "cnuasgpu: TX range exceeds device memory\n"); + return; + } + + sent =3D send(s->socket_fd, source, s->tx_len, MSG_NOSIGNAL); + if (sent < 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "cnuasgpu: link transmit failed: %s\n", + strerror(errno)); + if (errno !=3D EAGAIN && errno !=3D EWOULDBLOCK) { + cnuas_gpu_disconnect(s); + } + return; + } + if (sent !=3D s->tx_len) { + qemu_log_mask(LOG_GUEST_ERROR, + "cnuasgpu: short TX (%zd of %u bytes)\n", + sent, s->tx_len); + return; + } + + s->irq_status |=3D CNUAS_GPU_IRQ_TX_DONE; + cnuas_gpu_update_irq(s); +} + +static uint64_t cnuas_gpu_bar0_read(void *opaque, hwaddr addr, + unsigned size) +{ + CnuasGpuState *s =3D opaque; + + switch (addr) { + case CNUAS_GPU_REG_VENDOR_ID: + return PCI_VENDOR_ID_REDHAT; + case CNUAS_GPU_REG_DEVICE_ID: + return PCI_DEVICE_ID_REDHAT_CNUASGPU; + case CNUAS_GPU_REG_REVISION: + return CNUAS_GPU_REVISION; + case CNUAS_GPU_REG_FW_VERSION: + return CNUAS_GPU_FW_VERSION; + case CNUAS_GPU_REG_GPU_ID: + return s->gpu_id; + case CNUAS_GPU_REG_SM_COUNT: + return s->sm_count; + case CNUAS_GPU_REG_LANES_PER_SM: + return s->lanes_per_sm; + case CNUAS_GPU_REG_TENSOR_SIZE: + return s->tensor_size; + case CNUAS_GPU_REG_DEVMEM_SIZE_LO: + return s->devmem_size; + case CNUAS_GPU_REG_DEVMEM_SIZE_HI: + return s->devmem_size >> 32; + case CNUAS_GPU_REG_IRQ_STATUS: + return s->irq_status; + case CNUAS_GPU_REG_IRQ_MASK: + return s->irq_mask; + case CNUAS_GPU_REG_LINK_STATUS: + return (s->link_up ? CNUAS_GPU_LINK_UP : 0) | + (s->rx_ready ? CNUAS_GPU_LINK_RX_READY : 0); + case CNUAS_GPU_REG_TX_OFFSET_LO: + return s->tx_offset_lo; + case CNUAS_GPU_REG_TX_OFFSET_HI: + return s->tx_offset_hi; + case CNUAS_GPU_REG_TX_LEN: + return s->tx_len; + case CNUAS_GPU_REG_RX_OFFSET_LO: + return s->rx_offset_lo; + case CNUAS_GPU_REG_RX_OFFSET_HI: + return s->rx_offset_hi; + case CNUAS_GPU_REG_RX_BUF_SIZE: + return s->rx_buf_size; + case CNUAS_GPU_REG_RX_LEN: + return s->rx_len; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "cnuasgpu: read from unknown register 0x%" + HWADDR_PRIx "\n", addr); + return 0; + } +} + +static void cnuas_gpu_bar0_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + CnuasGpuState *s =3D opaque; + + switch (addr) { + case CNUAS_GPU_REG_IRQ_STATUS: + s->irq_status &=3D ~value; + cnuas_gpu_update_irq(s); + break; + case CNUAS_GPU_REG_IRQ_MASK: + s->irq_mask =3D value; + cnuas_gpu_update_irq(s); + break; + case CNUAS_GPU_REG_TX_OFFSET_LO: + s->tx_offset_lo =3D value; + break; + case CNUAS_GPU_REG_TX_OFFSET_HI: + s->tx_offset_hi =3D value; + break; + case CNUAS_GPU_REG_TX_LEN: + s->tx_len =3D value; + break; + case CNUAS_GPU_REG_TX_DOORBELL: + if (value) { + cnuas_gpu_transmit(s); + } + break; + case CNUAS_GPU_REG_RX_OFFSET_LO: + s->rx_offset_lo =3D value; + break; + case CNUAS_GPU_REG_RX_OFFSET_HI: + s->rx_offset_hi =3D value; + break; + case CNUAS_GPU_REG_RX_BUF_SIZE: + s->rx_buf_size =3D value; + break; + case CNUAS_GPU_REG_RX_CONSUME: + if (value && s->rx_ready) { + s->rx_ready =3D false; + s->rx_len =3D 0; + if (s->socket_fd >=3D 0) { + qemu_set_fd_handler(s->socket_fd, + cnuas_gpu_receive_ready, NULL, s); + } + } + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "cnuasgpu: write to unknown register 0x%" + HWADDR_PRIx "\n", addr); + break; + } +} + +static const MemoryRegionOps cnuas_gpu_bar0_ops =3D { + .read =3D cnuas_gpu_bar0_read, + .write =3D cnuas_gpu_bar0_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + }, + .impl =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + }, +}; + +static void cnuas_gpu_reset_hold(Object *obj, ResetType type) +{ + CnuasGpuState *s =3D CNUAS_GPU(obj); + + s->irq_status =3D 0; + s->irq_mask =3D 0; + s->tx_offset_lo =3D 0; + s->tx_offset_hi =3D 0; + s->tx_len =3D 0; + s->rx_offset_lo =3D 0; + s->rx_offset_hi =3D 0; + s->rx_buf_size =3D 0; + s->rx_len =3D 0; + s->rx_ready =3D false; + pci_set_irq(&s->parent_obj, 0); + + if (s->socket_fd >=3D 0) { + qemu_set_fd_handler(s->socket_fd, cnuas_gpu_receive_ready, NULL, s= ); + } +} + +static int cnuas_gpu_post_load(void *opaque, int version_id) +{ + CnuasGpuState *s =3D opaque; + + if (s->socket_fd >=3D 0) { + qemu_set_fd_handler(s->socket_fd, + s->rx_ready ? NULL : cnuas_gpu_receive_ready, + NULL, s); + } + cnuas_gpu_update_irq(s); + return 0; +} + +static const VMStateDescription vmstate_cnuas_gpu =3D { + .name =3D TYPE_CNUAS_GPU, + .version_id =3D 1, + .minimum_version_id =3D 1, + .post_load =3D cnuas_gpu_post_load, + .fields =3D (const VMStateField[]) { + VMSTATE_PCI_DEVICE(parent_obj, CnuasGpuState), + VMSTATE_UINT32(irq_status, CnuasGpuState), + VMSTATE_UINT32(irq_mask, CnuasGpuState), + VMSTATE_UINT32(tx_offset_lo, CnuasGpuState), + VMSTATE_UINT32(tx_offset_hi, CnuasGpuState), + VMSTATE_UINT32(tx_len, CnuasGpuState), + VMSTATE_UINT32(rx_offset_lo, CnuasGpuState), + VMSTATE_UINT32(rx_offset_hi, CnuasGpuState), + VMSTATE_UINT32(rx_buf_size, CnuasGpuState), + VMSTATE_UINT32(rx_len, CnuasGpuState), + VMSTATE_BOOL(rx_ready, CnuasGpuState), + VMSTATE_END_OF_LIST() + } +}; + +static void cnuas_gpu_realize(PCIDevice *pdev, Error **errp) +{ + CnuasGpuState *s =3D CNUAS_GPU(pdev); + + if (s->devmem_size < CNUAS_GPU_DEVMEM_MIN || + s->devmem_size > CNUAS_GPU_DEVMEM_MAX || + !is_power_of_2(s->devmem_size)) { + error_setg(errp, + "cnuasgpu: devmem_size must be a power of two from " + "%llu to %llu bytes", + (unsigned long long)CNUAS_GPU_DEVMEM_MIN, + (unsigned long long)CNUAS_GPU_DEVMEM_MAX); + return; + } + + pci_config_set_interrupt_pin(pdev->config, 1); + if (msi_init(pdev, 0, 1, true, false, errp)) { + return; + } + if (pcie_endpoint_cap_init(pdev, 0x80) < 0) { + error_setg(errp, "cnuasgpu: cannot initialize PCIe capability"); + msi_uninit(pdev); + return; + } + pcie_cap_fill_link_ep_usp(pdev, s->pcie_width, s->pcie_speed, false); + + memory_region_init_io(&s->bar0, OBJECT(s), &cnuas_gpu_bar0_ops, s, + "cnuasgpu-bar0", CNUAS_GPU_BAR0_SIZE); + pci_register_bar(pdev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar0); + + memory_region_init_ram(&s->bar1, OBJECT(s), "cnuasgpu-devmem", + s->devmem_size, errp); + if (*errp) { + pcie_cap_exit(pdev); + msi_uninit(pdev); + return; + } + pci_register_bar(pdev, 1, + PCI_BASE_ADDRESS_SPACE_MEMORY | + PCI_BASE_ADDRESS_MEM_PREFETCH | + PCI_BASE_ADDRESS_MEM_TYPE_64, + &s->bar1); + + s->socket_fd =3D -1; + cnuas_gpu_connect(s); +} + +static void cnuas_gpu_exit(PCIDevice *pdev) +{ + CnuasGpuState *s =3D CNUAS_GPU(pdev); + + cnuas_gpu_disconnect(s); + pcie_cap_exit(pdev); + msi_uninit(pdev); +} + +static const Property cnuas_gpu_properties[] =3D { + DEFINE_PROP_UINT32("gpu_id", CnuasGpuState, gpu_id, 0), + DEFINE_PROP_UINT32("sm_count", CnuasGpuState, sm_count, 16), + DEFINE_PROP_UINT32("lanes_per_sm", CnuasGpuState, lanes_per_sm, 32), + DEFINE_PROP_UINT32("tensor_size", CnuasGpuState, tensor_size, 16), + DEFINE_PROP_SIZE("devmem_size", CnuasGpuState, devmem_size, + CNUAS_GPU_DEVMEM_DEFAULT), + DEFINE_PROP_STRING("cnuaslink_socket", CnuasGpuState, link_socket), + DEFINE_PROP_PCIE_LINK_SPEED("x-speed", CnuasGpuState, pcie_speed, + PCIE_LINK_SPEED_32), + DEFINE_PROP_PCIE_LINK_WIDTH("x-width", CnuasGpuState, pcie_width, + PCIE_LINK_WIDTH_16), +}; + +static void cnuas_gpu_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + PCIDeviceClass *pc =3D PCI_DEVICE_CLASS(klass); + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + + pc->realize =3D cnuas_gpu_realize; + pc->exit =3D cnuas_gpu_exit; + pc->vendor_id =3D PCI_VENDOR_ID_REDHAT; + pc->device_id =3D PCI_DEVICE_ID_REDHAT_CNUASGPU; + pc->class_id =3D PCI_CLASS_PROCESSOR_CO; + pc->revision =3D CNUAS_GPU_REVISION; + + rc->phases.hold =3D cnuas_gpu_reset_hold; + dc->desc =3D "CnuasGPU virtual accelerator"; + dc->vmsd =3D &vmstate_cnuas_gpu; + device_class_set_props(dc, cnuas_gpu_properties); + set_bit(DEVICE_CATEGORY_MISC, dc->categories); +} + +static const TypeInfo cnuas_gpu_info =3D { + .name =3D TYPE_CNUAS_GPU, + .parent =3D TYPE_PCI_DEVICE, + .instance_size =3D sizeof(CnuasGpuState), + .class_init =3D cnuas_gpu_class_init, + .interfaces =3D (const InterfaceInfo[]) { + { INTERFACE_PCIE_DEVICE }, + { }, + }, +}; + +static void cnuas_gpu_register_types(void) +{ + type_register_static(&cnuas_gpu_info); +} + +type_init(cnuas_gpu_register_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 9790afa104..beb3a678a5 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -1,6 +1,7 @@ system_ss.add(when: 'CONFIG_APPLESMC', if_true: files('applesmc.c')) =20 system_ss.add(when: 'CONFIG_EDU', if_true: files('edu.c')) +system_ss.add(when: 'CONFIG_CNUAS_GPU', if_true: files('cnuasgpu.c')) system_ss.add(when: 'CONFIG_FW_CFG_DMA', if_true: files('vmcoreinfo.c')) system_ss.add(when: 'CONFIG_ISA_DEBUG', if_true: files('debugexit.c')) system_ss.add(when: 'CONFIG_ISA_TESTDEV', if_true: files('pc-testdev.c')) --=20 2.43.0 From nobody Sat Sep 26 20:01:29 2026 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=fail(p=none dis=none) header.from=packetfive.com ARC-Seal: i=1; a=rsa-sha256; t=1790116356; cv=none; d=zohomail.com; s=zohoarc; b=SNujaX6gg+7jQseabyhP/im3tXeLVXzpThmleiwgylNoXB+JwA4D5+oYjky2fWc/mcjcdRMpNdPlYIm4sSDYz0ng4FE0iGg3dLJ1NGpeHZ9+5215BBeMUrxwtGXm+VFb2S0oI54HiGFdH0ocIIY0kPFBRg18UVLn5tjddIP5o/M= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790116356; 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:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=sCEjWHm8NN7Zv7BCQyuI8HoN0rLiN7MNBzuT07/ps18=; b=Dbww/QsWOqqreszJr+n2csVzRGagEr/j5gSdfJpCtrs1jjNNknCmL2CYOHgGfOd/NzbDNkv2ZDD51ZfZB801SQ3h2kTvXQviPMFXwSHGG1cu1++bQ3dQDf8t222J0D11Duif66m15ZtRqLKckN+Exp/Ff7qcmmqvAbUtRTAOxB8= 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=fail header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1790116356726920.9180529314946; Tue, 22 Sep 2026 15:32:36 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x991d-0004QG-0j; Tue, 22 Sep 2026 18:31:45 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x991K-0004MO-Md for qemu-devel@nongnu.org; Tue, 22 Sep 2026 18:31:26 -0400 Received: from mail-ed1-x534.google.com ([2a00:1450:4864:20::534]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1x991I-0004Mk-JB for qemu-devel@nongnu.org; Tue, 22 Sep 2026 18:31:26 -0400 Received: by mail-ed1-x534.google.com with SMTP id 4fb4d7f45d1cf-6aa8d04fcddso653952a12.0 for ; Tue, 22 Sep 2026 15:31:24 -0700 (PDT) Received: from node-dev.home (86-45-19-184-dynamic.agg1.roc.bbh-prp.eircom.net. [86.45.19.184]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-6aab3883151sm411663a12.14.2026.09.22.15.31.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 22 Sep 2026 15:31:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=packetfive-com.20251104.gappssmtp.com; s=20251104; t=1790116283; x=1790721083; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=sCEjWHm8NN7Zv7BCQyuI8HoN0rLiN7MNBzuT07/ps18=; b=qA6T3FE81djzU/tlCKPXWsEMeA78LDPac9AzrtAWS6SF84AzrTgc7tYg5arYCwiR7y TROPkDJaigaaMb2V2BWWdymzJMDfQUiMqCkvAJTTIXsAijvG3CsROgBX/WEuZ8Tn7e+7 MlVpg+9FgaHwT2sOER9X28DARh+JCei3MzJlewZo9I2JuupsIitOYva6DqGu9HRnqbHe kKuwE+lJKSTwqw7NqIcvBKMNqeVT+eCs43b1fMJFF9sV7W2x/c8zzRxNyyJeyke3IrNP LOVDnp6tM0LfV0cBOYnEljVUPbzFA/gFuJ6o4Hxm5qa2DxZeRCc8o7Y0Rmfl6BcY2p6T DESA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790116283; x=1790721083; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=sCEjWHm8NN7Zv7BCQyuI8HoN0rLiN7MNBzuT07/ps18=; b=vlc6zHLD0yFKxjG24A1nt5Aa/IcJkifNzCQF18u0AT++2dhfWwxSvSVj3L30JWpoKl 837JhL0Y1ZmVNoFfdJebLF3Hoiqt9AOfnXPCSK2lveBJhYe8Nk60PmpNzhQ1zfqYMAHD 8rRadLlyMn/dddfwU8RGjYDkW4HL5FehXkT1YEtTQXWtFn2f988HqnhUGGn8Isrkuu5c 5q2Y60xX4R3SaZDPyyBUjsUEvSoETHUQb6hw8zhewe01+GuwvB9ptUr5KwjdpkQaYnfS Pd1lC3ooE2PvvibBmGESoFtuBeez2tlZOxMPdJOPuuiwAXq6eLV3qP5v+I4hjyumNtPs sEQw== X-Gm-Message-State: AFuF++ki9YvOhgrJKffV76oMaM7OmHDJbh/Rz+MWZuV5aIlr27LAqInp IKIDdhFt2HkXKv6wJzjRBrhPZnSsRKTIx2qzHHnci10SN7X/kmZht8UtTKJ5OQ2eAjBhtwSzGdT xtnxn3bU= X-Gm-Gg: AYBFou0JrY4ZytYIokEPTpqz9sJLnabfxS+xZsehwSQ3x0XkNj3HApCGhms37QB8N/b 6NHeD3gg9YEyDP+Jwh/FAvkVxHbIYs3CkEn4vwoK5LcySoI1WE26UBjLw0hrv/pwiJ4FKc1v7Bt cPPaj0esSiliU3L06EQ1udJaNErFhQH3LDOU69DvUxxMQ9MFpBxGA9q6KZ/zlCZHlS1LMhCOkVz fcbCkDjeySD7urdBFLIgXVbx8GpF7K2CxfCUh0dbLchLD0beNSlJYQ5BDbDycE50Gg93PMlphRP nGccVBqn/CsepqSC7FPk5Nrg+wvcr3dGacj2VaRU/gSOodf6d/jWyYgBDfu8xvW5rXDdJxdFx/P jrOla4zC2dAW7dDx6B184BSbqe0bIAAz02+5NZIvl3pNlDN5qGa+GeoBZnmsPjXFAl2MHkDyaTD YDJHFyNVS5BHYIbQZ+hbVJ4HRXsW680P2ULvqx5M3gaQbEIO9R4xq3gvS1a7BsIfis9KKrCbtaY wFb5n4t4JWzif5+mm9OTudl+LldGHLXwIIoCiE5j0IkjOfg8txZZ16XWwCtCvr80Rzt0sh+hbM+ X-Received: by 2002:a05:6402:332:b0:6a9:a0ca:ea5c with SMTP id 4fb4d7f45d1cf-6aa9feb3b0amr2831076a12.5.1790116282986; Tue, 22 Sep 2026 15:31:22 -0700 (PDT) From: Weqaar Janjua To: qemu-devel@nongnu.org Cc: kraxel@redhat.com, mst@redhat.com, pierrick.bouvier@oss.qualcomm.com, jasowangio@gmail.com, pbonzini@redhat.com, farosas@suse.de, lvivier@redhat.com Subject: [PATCH v2 6/6] tests/qtest: Add CnuasGPU tests Date: Tue, 22 Sep 2026 22:30:45 +0000 Message-ID: <20260922223045.190062-7-weqaar.janjua@packetfive.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260922223045.190062-1-weqaar.janjua@packetfive.com> References: <20260922223045.190062-1-weqaar.janjua@packetfive.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=lists1p.gnu.org; Received-SPF: none client-ip=2a00:1450:4864:20::534; envelope-from=weqaar.janjua@packetfive.com; helo=mail-ed1-x534.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_NONE=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 development 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 @packetfive-com.20251104.gappssmtp.com) X-ZM-MESSAGEID: 1790116357971158500 Content-Type: text/plain; charset="utf-8" Cover PCI identity, registers, device memory, reset, and link transport. Signed-off-by: Weqaar Janjua --- MAINTAINERS | 1 + tests/qtest/cnuasgpu-test.c | 274 ++++++++++++++++++++++++++++++++++++ tests/qtest/meson.build | 1 + 3 files changed, 276 insertions(+) create mode 100644 tests/qtest/cnuasgpu-test.c diff --git a/MAINTAINERS b/MAINTAINERS index d11ea29ff9..bb38cd1b4a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2780,6 +2780,7 @@ F: docs/specs/cnuasgpu.rst F: hw/misc/cnuasgpu.c F: hw/net/cnuas_vnic.c F: tests/qtest/cnuas-vnic-test.c +F: tests/qtest/cnuasgpu-test.c =20 VMware M: Dmitry Fleytman diff --git a/tests/qtest/cnuasgpu-test.c b/tests/qtest/cnuasgpu-test.c new file mode 100644 index 0000000000..3ac3b20b32 --- /dev/null +++ b/tests/qtest/cnuasgpu-test.c @@ -0,0 +1,274 @@ +/* + * QTest for the CnuasGPU virtual accelerator + * + * Copyright (c) 2026 PacketFive + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "hw/pci/pci.h" +#include "hw/pci/pci_regs.h" +#include "libqos/pci.h" +#include "libqos/pci-pc.h" +#include "libqtest.h" + +#include +#include + +#define CNUAS_GPU_DEVFN QPCI_DEVFN(4, 0) +#define CNUAS_GPU_BAR0_SIZE (64 * KiB) +#define CNUAS_GPU_BAR1_SIZE (16 * MiB) +#define CNUAS_GPU_REG_VENDOR_ID 0x000 +#define CNUAS_GPU_REG_DEVICE_ID 0x004 +#define CNUAS_GPU_REG_REVISION 0x008 +#define CNUAS_GPU_REG_FW_VERSION 0x00c +#define CNUAS_GPU_REG_GPU_ID 0x010 +#define CNUAS_GPU_REG_SM_COUNT 0x014 +#define CNUAS_GPU_REG_LANES_PER_SM 0x018 +#define CNUAS_GPU_REG_TENSOR_SIZE 0x01c +#define CNUAS_GPU_REG_DEVMEM_SIZE_LO 0x020 +#define CNUAS_GPU_REG_DEVMEM_SIZE_HI 0x024 +#define CNUAS_GPU_REG_IRQ_STATUS 0x100 +#define CNUAS_GPU_REG_IRQ_MASK 0x104 +#define CNUAS_GPU_REG_LINK_STATUS 0x200 +#define CNUAS_GPU_REG_TX_OFFSET_LO 0x204 +#define CNUAS_GPU_REG_TX_OFFSET_HI 0x208 +#define CNUAS_GPU_REG_TX_LEN 0x20c +#define CNUAS_GPU_REG_TX_DOORBELL 0x210 +#define CNUAS_GPU_REG_RX_OFFSET_LO 0x214 +#define CNUAS_GPU_REG_RX_OFFSET_HI 0x218 +#define CNUAS_GPU_REG_RX_BUF_SIZE 0x21c +#define CNUAS_GPU_REG_RX_LEN 0x220 +#define CNUAS_GPU_REG_RX_CONSUME 0x224 + +typedef struct CnuasGpuTest { + QTestState *qts; + QPCIBus *bus; + QPCIDevice *dev; + QPCIBar bar0; + QPCIBar bar1; +} CnuasGpuTest; + +static void cnuas_gpu_test_start_with_args(CnuasGpuTest *test, + const char *args) +{ + uint64_t bar_size; + + test->qts =3D qtest_initf("-machine q35 " + "-device cnuasgpu,addr=3D04.0,devmem_size=3D16= M," + "gpu_id=3D7,sm_count=3D24,lanes_per_sm=3D64," + "tensor_size=3D32%s", args); + test->bus =3D qpci_new_pc(test->qts, NULL); + test->dev =3D qpci_device_find(test->bus, CNUAS_GPU_DEVFN); + g_assert_nonnull(test->dev); + qpci_device_enable(test->dev); + + test->bar0 =3D qpci_iomap(test->dev, 0, &bar_size); + g_assert_cmpuint(bar_size, =3D=3D, CNUAS_GPU_BAR0_SIZE); + test->bar1 =3D qpci_iomap(test->dev, 1, &bar_size); + g_assert_cmpuint(bar_size, =3D=3D, CNUAS_GPU_BAR1_SIZE); +} + +static void cnuas_gpu_test_start(CnuasGpuTest *test) +{ + cnuas_gpu_test_start_with_args(test, ""); +} + +static void cnuas_gpu_test_stop(CnuasGpuTest *test) +{ + g_free(test->dev); + qpci_free_pc(test->bus); + qtest_quit(test->qts); +} + +static void cnuas_gpu_test_pci_config(void) +{ + CnuasGpuTest test; + + cnuas_gpu_test_start(&test); + + g_assert_cmphex(qpci_config_readw(test.dev, PCI_VENDOR_ID), =3D=3D, + PCI_VENDOR_ID_REDHAT); + g_assert_cmphex(qpci_config_readw(test.dev, PCI_DEVICE_ID), =3D=3D, + PCI_DEVICE_ID_REDHAT_CNUASGPU); + g_assert_cmphex(qpci_config_readw(test.dev, PCI_CLASS_DEVICE), =3D=3D, + PCI_CLASS_PROCESSOR_CO); + g_assert_cmphex(qpci_config_readb(test.dev, PCI_REVISION_ID), =3D=3D, = 1); + g_assert_cmphex(qpci_find_capability(test.dev, PCI_CAP_ID_MSI, 0), != =3D, 0); + + cnuas_gpu_test_stop(&test); +} + +static void cnuas_gpu_test_registers(void) +{ + CnuasGpuTest test; + + cnuas_gpu_test_start(&test); + + g_assert_cmphex(qpci_io_readl(test.dev, test.bar0, + CNUAS_GPU_REG_VENDOR_ID), =3D=3D, + PCI_VENDOR_ID_REDHAT); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar0, + CNUAS_GPU_REG_DEVICE_ID), =3D=3D, + PCI_DEVICE_ID_REDHAT_CNUASGPU); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar0, + CNUAS_GPU_REG_REVISION), =3D=3D, 1); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar0, + CNUAS_GPU_REG_FW_VERSION), =3D=3D, 0x000= 10000); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar0, + CNUAS_GPU_REG_GPU_ID), =3D=3D, 7); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar0, + CNUAS_GPU_REG_SM_COUNT), =3D=3D, 24); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar0, + CNUAS_GPU_REG_LANES_PER_SM), =3D=3D, 64); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar0, + CNUAS_GPU_REG_TENSOR_SIZE), =3D=3D, 32); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar0, + CNUAS_GPU_REG_DEVMEM_SIZE_LO), =3D=3D, + CNUAS_GPU_BAR1_SIZE); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar0, + CNUAS_GPU_REG_DEVMEM_SIZE_HI), =3D=3D, 0= ); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar0, + CNUAS_GPU_REG_LINK_STATUS), =3D=3D, 0); + + cnuas_gpu_test_stop(&test); +} + +static void cnuas_gpu_test_memory_and_reset(void) +{ + static const uint8_t pattern[] =3D { + 0x43, 0x6e, 0x75, 0x61, 0x73, 0x47, 0x50, 0x55, + }; + uint8_t result[sizeof(pattern)] =3D { 0 }; + CnuasGpuTest test; + + cnuas_gpu_test_start(&test); + + qpci_memwrite(test.dev, test.bar1, 0x1000, pattern, sizeof(pattern)); + qpci_memread(test.dev, test.bar1, 0x1000, result, sizeof(result)); + g_assert_cmpmem(result, sizeof(result), pattern, sizeof(pattern)); + + qpci_io_writel(test.dev, test.bar0, CNUAS_GPU_REG_IRQ_MASK, 3); + qpci_io_writel(test.dev, test.bar0, CNUAS_GPU_REG_TX_OFFSET_LO, + 0x12345678); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar0, + CNUAS_GPU_REG_IRQ_MASK), =3D=3D, 3); + + qtest_system_reset(test.qts); + qpci_device_enable(test.dev); + + g_assert_cmphex(qpci_io_readl(test.dev, test.bar0, + CNUAS_GPU_REG_IRQ_STATUS), =3D=3D, 0); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar0, + CNUAS_GPU_REG_IRQ_MASK), =3D=3D, 0); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar0, + CNUAS_GPU_REG_TX_OFFSET_LO), =3D=3D, 0); + + cnuas_gpu_test_stop(&test); +} + +static int cnuas_gpu_test_listen(char **path) +{ + struct sockaddr_un address =3D { .sun_family =3D AF_UNIX }; + int fd; + + *path =3D g_strdup_printf("/tmp/cnuasgpu-test-%u.sock", getpid()); + unlink(*path); + g_strlcpy(address.sun_path, *path, sizeof(address.sun_path)); + + fd =3D socket(AF_UNIX, SOCK_SEQPACKET, 0); + g_assert_cmpint(fd, >=3D, 0); + g_assert_cmpint(bind(fd, (struct sockaddr *)&address, sizeof(address)), + =3D=3D, 0); + g_assert_cmpint(listen(fd, 1), =3D=3D, 0); + return fd; +} + +static void cnuas_gpu_test_transport(void) +{ + static const uint8_t tx_frame[] =3D { + 0x43, 0x6e, 0x75, 0x61, 0x73, 0x4c, 0x69, 0x6e, 0x6b, + }; + static const uint8_t rx_frame[] =3D { + 0x70, 0x65, 0x65, 0x72, 0x2d, 0x66, 0x72, 0x61, 0x6d, 0x65, + }; + uint8_t result[64] =3D { 0 }; + const uint64_t tx_offset =3D 0x1000; + const uint64_t rx_offset =3D 0x2000; + g_autofree char *path =3D NULL; + g_autofree char *args =3D NULL; + CnuasGpuTest test; + int connection; + int listener; + unsigned int i; + + listener =3D cnuas_gpu_test_listen(&path); + args =3D g_strdup_printf(",cnuaslink_socket=3D%s", path); + cnuas_gpu_test_start_with_args(&test, args); + connection =3D accept(listener, NULL, NULL); + g_assert_cmpint(connection, >=3D, 0); + + g_assert_cmphex(qpci_io_readl(test.dev, test.bar0, + CNUAS_GPU_REG_LINK_STATUS), =3D=3D, 1); + + qpci_memwrite(test.dev, test.bar1, tx_offset, tx_frame, + sizeof(tx_frame)); + qpci_io_writel(test.dev, test.bar0, CNUAS_GPU_REG_TX_OFFSET_LO, + tx_offset); + qpci_io_writel(test.dev, test.bar0, CNUAS_GPU_REG_TX_OFFSET_HI, + tx_offset >> 32); + qpci_io_writel(test.dev, test.bar0, CNUAS_GPU_REG_TX_LEN, + sizeof(tx_frame)); + qpci_io_writel(test.dev, test.bar0, CNUAS_GPU_REG_TX_DOORBELL, 1); + + g_assert_cmpint(recv(connection, result, sizeof(result), 0), =3D=3D, + sizeof(tx_frame)); + g_assert_cmpmem(result, sizeof(tx_frame), tx_frame, sizeof(tx_frame)); + + qpci_io_writel(test.dev, test.bar0, CNUAS_GPU_REG_RX_OFFSET_LO, + rx_offset); + qpci_io_writel(test.dev, test.bar0, CNUAS_GPU_REG_RX_OFFSET_HI, + rx_offset >> 32); + qpci_io_writel(test.dev, test.bar0, CNUAS_GPU_REG_RX_BUF_SIZE, + sizeof(rx_frame)); + g_assert_cmpint(send(connection, rx_frame, sizeof(rx_frame), 0), =3D= =3D, + sizeof(rx_frame)); + + for (i =3D 0; i < 1000; i++) { + if (qpci_io_readl(test.dev, test.bar0, + CNUAS_GPU_REG_LINK_STATUS) =3D=3D 3) { + break; + } + g_usleep(1000); + } + g_assert_cmpuint(i, <, 1000); + g_assert_cmpuint(qpci_io_readl(test.dev, test.bar0, + CNUAS_GPU_REG_RX_LEN), =3D=3D, + sizeof(rx_frame)); + + memset(result, 0, sizeof(result)); + qpci_memread(test.dev, test.bar1, rx_offset, result, sizeof(rx_frame)); + g_assert_cmpmem(result, sizeof(rx_frame), rx_frame, sizeof(rx_frame)); + + qpci_io_writel(test.dev, test.bar0, CNUAS_GPU_REG_RX_CONSUME, 1); + g_assert_cmphex(qpci_io_readl(test.dev, test.bar0, + CNUAS_GPU_REG_LINK_STATUS), =3D=3D, 1); + + close(connection); + close(listener); + unlink(path); + cnuas_gpu_test_stop(&test); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + qtest_add_func("/cnuasgpu/pci-config", cnuas_gpu_test_pci_config); + qtest_add_func("/cnuasgpu/registers", cnuas_gpu_test_registers); + qtest_add_func("/cnuasgpu/memory-and-reset", + cnuas_gpu_test_memory_and_reset); + qtest_add_func("/cnuasgpu/transport", cnuas_gpu_test_transport); + return g_test_run(); +} diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 84d2fa702a..719bb107ca 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -60,6 +60,7 @@ qtests_i386 =3D \ (slirp.found() ? ['pxe-test'] : []) + \ qtests_filter + \ (config_all_devices.has_key('CONFIG_CNUAS_VNIC') ? ['cnuas-vnic-test'] := []) + \ + (config_all_devices.has_key('CONFIG_CNUAS_GPU') ? ['cnuasgpu-test'] : []= ) + \ (config_all_devices.has_key('CONFIG_ACPI_VMGENID') ? ['vmgenid-test'] : = []) + \ (config_all_devices.has_key('CONFIG_AHCI_ICH9') and have_tools ? ['ahci-= test'] : []) + \ (config_all_devices.has_key('CONFIG_AHCI_ICH9') ? ['tco-test'] : []) + = \ --=20 2.43.0