From patchwork Thu Mar 7 17:29:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 1053174 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="lbynUiDc"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44FdwC5h39z9s7T for ; Fri, 8 Mar 2019 05:10:35 +1100 (AEDT) Received: from localhost ([127.0.0.1]:56645 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h1xTV-0002Bv-Nt for incoming@patchwork.ozlabs.org; Thu, 07 Mar 2019 13:10:33 -0500 Received: from eggs.gnu.org ([209.51.188.92]:39479) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h1wqk-00038L-Tl for qemu-devel@nongnu.org; Thu, 07 Mar 2019 12:30:32 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1h1wqi-00083N-L7 for qemu-devel@nongnu.org; Thu, 07 Mar 2019 12:30:30 -0500 Received: from mail-wr1-x42c.google.com ([2a00:1450:4864:20::42c]:37342) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1h1wqi-00082i-9J for qemu-devel@nongnu.org; Thu, 07 Mar 2019 12:30:28 -0500 Received: by mail-wr1-x42c.google.com with SMTP id w6so18399405wrs.4 for ; Thu, 07 Mar 2019 09:30:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=lY5Hdj1Bewp9swhusikSQ4EeMP0GCpeqtL5VawAK+T0=; b=lbynUiDcsakII+mrLSxjr419OccXUmTCwvo3fAQfPXch4miMnUUkzWEjorNPvyk3MT 8WPokD0d6GUaEbz+L+oWHguqBVF5/IuVDFDSJOm7JE8jozdUzWYu+WyR6b4NL3C8FOFB EPd9c7q5oRvFc51LwXLTYaQGgT7e0rctsoXkqhzSX3fwvPs4nJgJ4AvsKjBBcD0Qwod7 OoxfH9k9TTWL6mPAgopD+wmK76TP4KxtHyRcMJjmHq6lw8Hhaes4oworLjnyucJV/xLv BxJUBaioobMDHsSec68dXctZRP1CnyRPEgKwGpmH49OZttTa1nojlH7SzqvNaAJvzWvj Rw5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=lY5Hdj1Bewp9swhusikSQ4EeMP0GCpeqtL5VawAK+T0=; b=dEZWyZbw4Rt15CmDqPwWwxJ0HN5E8cSRC+U/EHm7RDuxr0AY+L8CwHghetcqX0YoYN B+rNEwcs6f/dUWVn1J9uaUCYpRFshNCThjBgNFDGRHg8RSNI+udX+2ePtUCrWgukZrgd sogWygSMtwVmyGExWmJkOSwl92JBpeCmimlLe4ehcB/GJAusTTyWEYreCO/BbfjWDrMY v9OgpKmmNZAySDpONRDG5TjVNmsFxF/6SEp75mqdUBzGOScWg4B1l2r1wCPhqmK+tck3 RzK6ZEQNtE2hS9ulFPE0oMBfOVe0ugOh3bOPY6YKKGQx7vuPlWvg6vf+atKLVvWwKJKx zohw== X-Gm-Message-State: APjAAAUQxWqK5WvOxmPM3RohDbfVYcvIYUQiDNgPLLxyKtOlAVvfSDjl OSv2+iOyGBJgTsROZRm4/6T2+6n9 X-Google-Smtp-Source: APXvYqz/b/F7tmcztKjMOeh/U429t3dkk/S3oMu4zL9PtWBWYouqaLBVAxj1iO3ImWJhkFjZw7cXwA== X-Received: by 2002:adf:ce91:: with SMTP id r17mr7365434wrn.80.1551979826831; Thu, 07 Mar 2019 09:30:26 -0800 (PST) Received: from 640k.localdomain ([93.56.166.5]) by smtp.gmail.com with ESMTPSA id d206sm9979753wmc.11.2019.03.07.09.30.25 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 07 Mar 2019 09:30:26 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 7 Mar 2019 18:29:26 +0100 Message-Id: <1551979804-6060-20-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1551979804-6060-1-git-send-email-pbonzini@redhat.com> References: <1551979804-6060-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::42c Subject: [Qemu-devel] [PULL 19/57] tests/libqos: 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: thuth@redhat.com, Emanuele Giuseppe Esposito , lviver@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Emanuele Giuseppe Esposito 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 Signed-off-by: Paolo Bonzini --- tests/Makefile.include | 1 + tests/libqos/e1000e.c | 260 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/libqos/e1000e.h | 53 ++++++++++ 3 files changed, 314 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 a890327..5bd60a5 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -749,6 +749,7 @@ libqos-virtio-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) tests/libqos/virt # Devices qos-test-obj-y = tests/qos-test.o $(libqgraph-obj-y) qos-test-obj-y += $(libqos-pc-obj-y) $(libqos-spapr-obj-y) +qos-test-obj-y += tests/libqos/e1000e.o qos-test-obj-y += tests/libqos/sdhci.o # Machines diff --git a/tests/libqos/e1000e.c b/tests/libqos/e1000e.c new file mode 100644 index 0000000..54d3898 --- /dev/null +++ b/tests/libqos/e1000e.c @@ -0,0 +1,260 @@ +/* + * 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/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 = 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 = 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 = e1000e_macreg_read(d, E1000E_TDT); + uint32_t len = 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 = e1000e_macreg_read(d, E1000E_RDT); + uint32_t len = 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 = data; + memcpy(res, dev, sizeof(QPCIDevice)); + g_free(dev); +} + +void e1000e_wait_isr(QE1000E *d, uint16_t msg_id) +{ + QE1000E_PCI *d_pci = container_of(d, QE1000E_PCI, e1000e); + guint64 end_time = 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 = (QE1000E_PCI *) obj; + qpci_iounmap(&epci->pci_dev, epci->mac_regs); + qpci_msix_disable(&epci->pci_dev); +} + +static void e1000e_pci_start_hw(QOSGraphObject *obj) +{ + QE1000E_PCI *d = (QE1000E_PCI *) obj; + uint32_t val; + + /* Enable the device */ + qpci_device_enable(&d->pci_dev); + + /* Reset the device */ + val = 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 = e1000e_macreg_read(&d->e1000e, E1000E_STATUS); + g_assert_cmphex(val & (E1000E_STATUS_LU | E1000E_STATUS_ASDV1000), + ==, 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 = 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 = 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 = g_new0(QE1000E_PCI, 1); + QPCIBus *bus = pci_bus; + QPCIAddress *address = addr; + + qpci_device_foreach(bus, address->vendor_id, address->device_id, + e1000e_foreach_callback, &d->pci_dev); + + /* Map BAR0 (mac registers) */ + d->mac_regs = qpci_iomap(&d->pci_dev, 0, NULL); + + /* Allocate and setup TX ring */ + d->e1000e.tx_ring = guest_alloc(alloc, E1000E_RING_LEN); + g_assert(d->e1000e.tx_ring != 0); + + /* Allocate and setup RX ring */ + d->e1000e.rx_ring = guest_alloc(alloc, E1000E_RING_LEN); + g_assert(d->e1000e.rx_ring != 0); + + d->obj.get_driver = e1000e_pci_get_driver; + d->obj.start_hw = e1000e_pci_start_hw; + d->obj.destructor = e1000e_pci_destructor; + + return &d->obj; +} + +static void e1000e_register_nodes(void) +{ + QPCIAddress addr = { + .vendor_id = 0x8086, + .device_id = 0x10D3, + }; + + /* FIXME: every test using this node needs to setup a -netdev socket,id=hs0 + * otherwise QEMU is not going to start */ + QOSGraphEdgeOptions opts = { + .extra_device_opts = "netdev=hs0", + }; + 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 0000000..9d37094 --- /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