From nobody Wed Nov 5 10:47:35 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1534156181126287.0756142079234; Mon, 13 Aug 2018 03:29:41 -0700 (PDT) Received: from localhost ([::1]:38591 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fpA6V-0003Au-Un for importer@patchew.org; Mon, 13 Aug 2018 06:29:40 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:43690) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fp9sm-0007Kq-Iw for qemu-devel@nongnu.org; Mon, 13 Aug 2018 06:15:30 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fp9sk-00028P-E2 for qemu-devel@nongnu.org; Mon, 13 Aug 2018 06:15:28 -0400 Received: from mail-ed1-x535.google.com ([2a00:1450:4864:20::535]:43147) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fp9sk-00027e-35; Mon, 13 Aug 2018 06:15:26 -0400 Received: by mail-ed1-x535.google.com with SMTP id j21-v6so7941068edp.10; Mon, 13 Aug 2018 03:15:25 -0700 (PDT) Received: from localhost.localdomain ([194.230.159.125]) by smtp.gmail.com with ESMTPSA id s27-v6sm11670006edb.73.2018.08.13.03.15.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 13 Aug 2018 03:15:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=OulC+3RHWWpjYxKtXZNNGIk34CkXD0YqYYL5oUp1eJw=; b=rQbgQ0oy19GQLzUqVCTm/CNGN7Tm600Uniq3G/LnybG4GJvnBZluV0nOwYK3wifa4I sUjUhGY+BZoVY4aLHo6XVdF0LLTsXiBuQ2EfmAZdfGVQnGx/aVvfnQWJnIG7Jv8bZSwz XH28NF6NEaOOfSlF58K7Bvnr0CX3QjPmFvYcSqb5iCTJvhjZtkdlA5rMqkRCXToy/MxW 83Nr0U2gtEP3KkzReizxBDA8nav17vQlP/TILuvp6cm9R4CvvuSbGhYLiI8nsa9Pj0oM LGSyxbZbmX9sY/2sdgPaCLCbYl3tfBiNlAx4RFz9AIw2gld2gmyyULdFteBDwNUkyYlI lvVA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=OulC+3RHWWpjYxKtXZNNGIk34CkXD0YqYYL5oUp1eJw=; b=F+GEvWQ/jN9MRPFA4I+0Xut3qWMLQpYOJ48hfvP+MAPDii1H5T/kbvyCxgpujuHXFZ a2C0lJ/8r5sWG0DMuDfAh+MN/R+SxLY2XHw8tCSeaNUvHoNxPOj6Za/v2msO9SebF6Ep 0mCQqFQzdaLJo6XkY6Tu353C2eqa0w3wRnI4GQRHSMnhxbOjE6wb0L/krbaD/HnSvCIA RBoPEhAyHY3myaueepmBzNtgplZvBquxAW5hbgDLmCLWZ/ZijA6752g7MCubpdqFgrc0 gDVLFCvVsa9a79Zz6GiDlRJ9N+bXg+f8aI2l1gwrMd+Jpuny7TfnWtIfWluxRhjfISeT Nwww== X-Gm-Message-State: AOUpUlE7AR8pEK39PlpUqfikHqZ8pgOTgaAlxSC3resq1kZ6gfTcBQdH bYQRna34cDm0qnIjxtpQcSU4ftgYWwo= X-Google-Smtp-Source: AA+uWPytk8OwKOiK9vz95xKWOxFrrrr+1g+iSGxLXYyjC5G/opylE0O9clw3VBJVPtwf1xLYUTvD9Q== X-Received: by 2002:a50:b902:: with SMTP id m2-v6mr21388908ede.185.1534155324638; Mon, 13 Aug 2018 03:15:24 -0700 (PDT) From: Emanuele Giuseppe Esposito To: qemu-devel@nongnu.org Date: Mon, 13 Aug 2018 12:14:31 +0200 Message-Id: <20180813101453.10200-12-e.emanuelegiuseppe@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180813101453.10200-1-e.emanuelegiuseppe@gmail.com> References: <20180813101453.10200-1-e.emanuelegiuseppe@gmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::535 Subject: [Qemu-devel] [PATCH 11/33] tests/qgraph: e1000e driver and interface nodes X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Laurent Vivier , Fam Zheng , qemu-block@nongnu.org, "Michael S. Tsirkin" , Jason Wang , Amit Shah , Emanuele Giuseppe Esposito , Alexander Graf , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Greg Kurz , qemu-ppc@nongnu.org, Gerd Hoffmann , Stefan Hajnoczi , Paolo Bonzini , John Snow , David Gibson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDMRC_1 RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add qgraph nodes for virtio-e1000e. It consumes a pci-bus, and it's directly used by tests (e1000e is pci based). Signed-off-by: Emanuele Giuseppe Esposito --- tests/Makefile.include | 1 + tests/libqos/e1000e.c | 262 +++++++++++++++++++++++++++++++++++++++++ tests/libqos/e1000e.h | 53 +++++++++ 3 files changed, 316 insertions(+) create mode 100644 tests/libqos/e1000e.c create mode 100644 tests/libqos/e1000e.h diff --git a/tests/Makefile.include b/tests/Makefile.include index 7c712406e1..9f0d64f4ae 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -775,6 +775,7 @@ libqgraph-machines-obj-y +=3D tests/libqos/ppc64_pserie= s-machine.o libqgraph-pci-obj-y =3D $(libqos-pc-obj-y) $(libqos-spapr-obj-y) libqgraph-pci-obj-y +=3D $(libqgraph-machines-obj-y) libqgraph-pci-obj-y +=3D tests/libqos/sdhci.o +libqgraph-pci-obj-y +=3D tests/libqos/e1000e.o =20 libqgraph-tests-obj-y =3D $(libqgraph-pci-obj-y) libqgraph-tests-obj-y +=3D tests/sdhci-test.o diff --git a/tests/libqos/e1000e.c b/tests/libqos/e1000e.c new file mode 100644 index 0000000000..33dac5a88b --- /dev/null +++ b/tests/libqos/e1000e.c @@ -0,0 +1,262 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "qemu-common.h" +#include "libqos/pci-pc.h" +#include "qemu/sockets.h" +#include "qemu/iov.h" +#include "qemu/bitops.h" +#include "libqos/malloc.h" +#include "libqos/malloc-pc.h" +#include "libqos/malloc-generic.h" +#include "libqos/qgraph.h" +#include "e1000e.h" + +#define E1000E_IMS (0x00d0) + +#define E1000E_STATUS (0x0008) +#define E1000E_STATUS_LU BIT(1) +#define E1000E_STATUS_ASDV1000 BIT(9) + +#define E1000E_CTRL (0x0000) +#define E1000E_CTRL_RESET BIT(26) + +#define E1000E_RCTL (0x0100) +#define E1000E_RCTL_EN BIT(1) +#define E1000E_RCTL_UPE BIT(3) +#define E1000E_RCTL_MPE BIT(4) + +#define E1000E_RFCTL (0x5008) +#define E1000E_RFCTL_EXTEN BIT(15) + +#define E1000E_TCTL (0x0400) +#define E1000E_TCTL_EN BIT(1) + +#define E1000E_CTRL_EXT (0x0018) +#define E1000E_CTRL_EXT_DRV_LOAD BIT(28) +#define E1000E_CTRL_EXT_TXLSFLOW BIT(22) + +#define E1000E_IVAR (0x00E4) +#define E1000E_IVAR_TEST_CFG ((E1000E_RX0_MSG_ID << 0) | BIT(3) = | \ + (E1000E_TX0_MSG_ID << 8) | BIT(11)= | \ + (E1000E_OTHER_MSG_ID << 16) | BIT(19)= | \ + BIT(31)) + +#define E1000E_RING_LEN (0x1000) + +#define E1000E_TDBAL (0x3800) + +#define E1000E_TDBAH (0x3804) +#define E1000E_TDH (0x3810) + +#define E1000E_RDBAL (0x2800) +#define E1000E_RDBAH (0x2804) +#define E1000E_RDH (0x2810) + +#define E1000E_TXD_LEN (16) +#define E1000E_RXD_LEN (16) + +static void e1000e_macreg_write(QE1000E *d, uint32_t reg, uint32_t val) +{ + QE1000E_PCI *d_pci =3D container_of(d, QE1000E_PCI, e1000e); + qpci_io_writel(&d_pci->pci_dev, d_pci->mac_regs, reg, val); +} + +static uint32_t e1000e_macreg_read(QE1000E *d, uint32_t reg) +{ + QE1000E_PCI *d_pci =3D container_of(d, QE1000E_PCI, e1000e); + return qpci_io_readl(&d_pci->pci_dev, d_pci->mac_regs, reg); +} + +void e1000e_tx_ring_push(QE1000E *d, void *descr) +{ + uint32_t tail =3D e1000e_macreg_read(d, E1000E_TDT); + uint32_t len =3D e1000e_macreg_read(d, E1000E_TDLEN) / E1000E_TXD_LEN; + + memwrite(d->tx_ring + tail * E1000E_TXD_LEN, descr, E1000E_TXD_LEN); + e1000e_macreg_write(d, E1000E_TDT, (tail + 1) % len); + + /* Read WB data for the packet transmitted */ + memread(d->tx_ring + tail * E1000E_TXD_LEN, descr, E1000E_TXD_LEN); +} + +void e1000e_rx_ring_push(QE1000E *d, void *descr) +{ + uint32_t tail =3D e1000e_macreg_read(d, E1000E_RDT); + uint32_t len =3D e1000e_macreg_read(d, E1000E_RDLEN) / E1000E_RXD_LEN; + + memwrite(d->rx_ring + tail * E1000E_RXD_LEN, descr, E1000E_RXD_LEN); + e1000e_macreg_write(d, E1000E_RDT, (tail + 1) % len); + + /* Read WB data for the packet received */ + memread(d->rx_ring + tail * E1000E_RXD_LEN, descr, E1000E_RXD_LEN); +} + +static void e1000e_foreach_callback(QPCIDevice *dev, int devfn, void *data) +{ + QPCIDevice *res =3D data; + memcpy(res, dev, sizeof(QPCIDevice)); +} + +void e1000e_wait_isr(QE1000E *d, uint16_t msg_id) +{ + QE1000E_PCI *d_pci =3D container_of(d, QE1000E_PCI, e1000e); + guint64 end_time =3D g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND; + + do { + if (qpci_msix_pending(&d_pci->pci_dev, msg_id)) { + return; + } + clock_step(10000); + } while (g_get_monotonic_time() < end_time); + + g_error("Timeout expired"); +} + +static void e1000e_pci_destructor(QOSGraphObject *obj) +{ + QE1000E_PCI *epci =3D (QE1000E_PCI *) obj; + qpci_iounmap(&epci->pci_dev, epci->mac_regs); + qpci_msix_disable(&epci->pci_dev); + g_free(epci); +} + +static void e1000e_pci_start_hw(QOSGraphObject *obj) +{ + QE1000E_PCI *d =3D (QE1000E_PCI *) obj; + uint32_t val; + + /* Enable the device */ + qpci_device_enable(&d->pci_dev); + + /* Reset the device */ + val =3D e1000e_macreg_read(&d->e1000e, E1000E_CTRL); + e1000e_macreg_write(&d->e1000e, E1000E_CTRL, val | E1000E_CTRL_RESET); + + /* Enable and configure MSI-X */ + qpci_msix_enable(&d->pci_dev); + e1000e_macreg_write(&d->e1000e, E1000E_IVAR, E1000E_IVAR_TEST_CFG); + + /* Check the device status - link and speed */ + val =3D e1000e_macreg_read(&d->e1000e, E1000E_STATUS); + g_assert_cmphex(val & (E1000E_STATUS_LU | E1000E_STATUS_ASDV1000), + =3D=3D, E1000E_STATUS_LU | E1000E_STATUS_ASDV1000); + + /* Initialize TX/RX logic */ + e1000e_macreg_write(&d->e1000e, E1000E_RCTL, 0); + e1000e_macreg_write(&d->e1000e, E1000E_TCTL, 0); + + /* Notify the device that the driver is ready */ + val =3D e1000e_macreg_read(&d->e1000e, E1000E_CTRL_EXT); + e1000e_macreg_write(&d->e1000e, E1000E_CTRL_EXT, + val | E1000E_CTRL_EXT_DRV_LOAD | E1000E_CTRL_EXT_TXLSFLOW); + + e1000e_macreg_write(&d->e1000e, E1000E_TDBAL, + (uint32_t) d->e1000e.tx_ring); + e1000e_macreg_write(&d->e1000e, E1000E_TDBAH, + (uint32_t) (d->e1000e.tx_ring >> 32)); + e1000e_macreg_write(&d->e1000e, E1000E_TDLEN, E1000E_RING_LEN); + e1000e_macreg_write(&d->e1000e, E1000E_TDT, 0); + e1000e_macreg_write(&d->e1000e, E1000E_TDH, 0); + + /* Enable transmit */ + e1000e_macreg_write(&d->e1000e, E1000E_TCTL, E1000E_TCTL_EN); + e1000e_macreg_write(&d->e1000e, E1000E_RDBAL, + (uint32_t)d->e1000e.rx_ring); + e1000e_macreg_write(&d->e1000e, E1000E_RDBAH, + (uint32_t)(d->e1000e.rx_ring >> 32)); + e1000e_macreg_write(&d->e1000e, E1000E_RDLEN, E1000E_RING_LEN); + e1000e_macreg_write(&d->e1000e, E1000E_RDT, 0); + e1000e_macreg_write(&d->e1000e, E1000E_RDH, 0); + + /* Enable receive */ + e1000e_macreg_write(&d->e1000e, E1000E_RFCTL, E1000E_RFCTL_EXTEN); + e1000e_macreg_write(&d->e1000e, E1000E_RCTL, E1000E_RCTL_EN | + E1000E_RCTL_UPE | + E1000E_RCTL_MPE); + + /* Enable all interrupts */ + e1000e_macreg_write(&d->e1000e, E1000E_IMS, 0xFFFFFFFF); + +} + +static void *e1000e_pci_get_driver(void *obj, const char *interface) +{ + QE1000E_PCI *epci =3D obj; + if (!g_strcmp0(interface, "e1000e-if")) { + return &epci->e1000e; + } + + /* implicit contains */ + if (!g_strcmp0(interface, "pci-device")) { + return &epci->pci_dev; + } + + fprintf(stderr, "%s not present in e1000e\n", interface); + g_assert_not_reached(); +} + +static void *e1000e_pci_create(void *pci_bus, QGuestAllocator *alloc, + void *addr) +{ + QE1000E_PCI *d =3D g_new0(QE1000E_PCI, 1); + QPCIBus *bus =3D pci_bus; + QPCIAddress *address =3D addr; + + qpci_device_foreach(bus, address->vendor_id, address->device_id, + e1000e_foreach_callback, &d->pci_dev); + + /* Map BAR0 (mac registers) */ + d->mac_regs =3D qpci_iomap(&d->pci_dev, 0, NULL); + + /* Allocate and setup TX ring */ + d->e1000e.tx_ring =3D guest_alloc(alloc, E1000E_RING_LEN); + g_assert(d->e1000e.tx_ring !=3D 0); + + /* Allocate and setup RX ring */ + d->e1000e.rx_ring =3D guest_alloc(alloc, E1000E_RING_LEN); + g_assert(d->e1000e.rx_ring !=3D 0); + + d->obj.get_driver =3D e1000e_pci_get_driver; + d->obj.start_hw =3D e1000e_pci_start_hw; + d->obj.destructor =3D e1000e_pci_destructor; + + return &d->obj; +} + +static void e1000e_register_nodes(void) +{ + QPCIAddress addr =3D { + .vendor_id =3D 0x8086, + .device_id =3D 0x10D3, + }; + + /* FIXME: every test using this node needs to setup a -netdev socket,i= d=3Dhs0 + * otherwise QEMU is not going to start */ + QOSGraphEdgeOptions opts =3D { + .extra_device_opts =3D "netdev=3Dhs0", + }; + add_qpci_address(&opts, &addr); + + qos_node_create_driver("e1000e", e1000e_pci_create); + qos_node_consumes("e1000e", "pci-bus", &opts); +} + +libqos_init(e1000e_register_nodes); diff --git a/tests/libqos/e1000e.h b/tests/libqos/e1000e.h new file mode 100644 index 0000000000..9d37094f43 --- /dev/null +++ b/tests/libqos/e1000e.h @@ -0,0 +1,53 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + */ + +#ifndef QGRAPH_E1000E +#define QGRAPH_E1000E + +#include "libqos/qgraph.h" +#include "pci.h" + +#define E1000E_RX0_MSG_ID (0) +#define E1000E_TX0_MSG_ID (1) +#define E1000E_OTHER_MSG_ID (2) + +#define E1000E_TDLEN (0x3808) +#define E1000E_TDT (0x3818) +#define E1000E_RDLEN (0x2808) +#define E1000E_RDT (0x2818) + +typedef struct QE1000E QE1000E; +typedef struct QE1000E_PCI QE1000E_PCI; + +struct QE1000E { + uint64_t tx_ring; + uint64_t rx_ring; +}; + +struct QE1000E_PCI { + QOSGraphObject obj; + QPCIDevice pci_dev; + QPCIBar mac_regs; + QE1000E e1000e; +}; + +void e1000e_wait_isr(QE1000E *d, uint16_t msg_id); +void e1000e_tx_ring_push(QE1000E *d, void *descr); +void e1000e_rx_ring_push(QE1000E *d, void *descr); + +#endif --=20 2.17.1