From patchwork Mon Mar 9 14:56:39 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Marchand X-Patchwork-Id: 3940 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id 87C0B9A9F; Mon, 9 Mar 2015 15:56:47 +0100 (CET) Received: from mail-wi0-f179.google.com (mail-wi0-f179.google.com [209.85.212.179]) by dpdk.org (Postfix) with ESMTP id 721B89A97 for ; Mon, 9 Mar 2015 15:56:45 +0100 (CET) Received: by wiwl15 with SMTP id l15so21561240wiw.0 for ; Mon, 09 Mar 2015 07:56:45 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=1WldtJDZy3zt1KogX3QHhSgc8f+lVNrJcYCfaey5mXg=; b=kBHYLl3E2FDBXiIuX3oZcqMycNgkiI95iNEv/1ouBWJ9v9J8vbI5fUE3JA5gEwBBHL ohzMiIJNMu/13USHL4ZL3xfoYHWRhTE9IR22uEoZYt6c0b+C/cpkBdwXoEFMIWbfbQ9N z+PbLxpREWyfD+6Bj30H/LODU5RvRNWrsx/YkliPi7w4Q4CtYQ5Y+9l9tVVGq9chJzFW waSkLcqUxWtCCjTzldf7J4QH1/kOXOTKQqjmNJhtfHkQwCHIfibZI0fStW04fbTFXCJr 7/7BHf/V4nnU+2AeHDgiXvVk+8btMZ+eCIDWreBZ/3h6ZTy/VjBrr4JBEJrk1dnKrgXK zzFg== X-Gm-Message-State: ALoCoQlQPgR3bBbOZQy6RnozStJGhtT6FFRTaeGCsJndejGeYlPlVNCpcqiFdg4RRAKomThOreYH X-Received: by 10.194.85.129 with SMTP id h1mr59383160wjz.147.1425913005298; Mon, 09 Mar 2015 07:56:45 -0700 (PDT) Received: from alcyon.dev.6wind.com (6wind.net2.nerim.net. [213.41.180.237]) by mx.google.com with ESMTPSA id vq9sm26984115wjc.6.2015.03.09.07.56.43 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 09 Mar 2015 07:56:44 -0700 (PDT) From: David Marchand To: dev@dpdk.org Date: Mon, 9 Mar 2015 15:56:39 +0100 Message-Id: <1425912999-13118-3-git-send-email-david.marchand@6wind.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1425912999-13118-1-git-send-email-david.marchand@6wind.com> References: <1425912999-13118-1-git-send-email-david.marchand@6wind.com> Subject: [dpdk-dev] [PATCH 2/2] virtio: change io privilege level as early as possible X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Playing with virtio link status triggers a segfault because of an incorrect io privilege level. To reproduce the problem, virtio device must be bound to igb_uio to have lsc enabled. $ lspci |grep Ethernet 00:03.0 Ethernet controller: Red Hat, Inc Virtio network device $ modprobe uio $ insmod ./x86_64-native-linuxapp-gcc/kmod/igb_uio.ko $ echo 0000:00:03.0 > /sys/bus/pci/devices/0000\:00\:03.0/driver/unbind $ echo 1af4 1000 > /sys/bus/pci/drivers/igb_uio/new_id $ ./x86_64-native-linuxapp-gcc/app/testpmd -c 0x6 -n 3 -w 0000:00:03.0 -- -i --txqflags=0xf01 [snip] EAL: PCI device 0000:00:03.0 on NUMA socket -1 EAL: probe driver: 1af4:1000 rte_virtio_pmd Interactive-mode selected Configuring Port 0 (socket 0) Port 0: DE:AD:DE:01:02:03 Checking link statuses... Port 0 Link Up - speed 10000 Mbps - full-duplex Done testpmd> Then, from qemu monitor: (qemu) set_link virtio-net-pci.0 off testpmd> Segmentation fault A call to rte_eal_iopl_init() in a specific constructor has been added so that, on Linux, iopl() is called asap: - for statically linked virtio pmd, the constructor will be called at binary start, - for shared virtio pmd (loaded using -d eal option), it will be called at dlopen() in rte_eal_init(). On linux, iopl() effects are inherited by children threads, so calling it in a constructor will ensure that any thread / process created after rte_eal_init() inherits the io privilege level needed by the pmd. We keep call to rte_eal_iopl_init() in the pmd init macro so that the pmd will not register if the io privilege level is insufficient. Besides, I moved rte_virtio_pmd_init() and related structure near its calling site, so that all init code can be looked at in a glance. The only change here is a new comment. Signed-off-by: David Marchand --- lib/librte_pmd_virtio/virtio_ethdev.c | 71 ++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index d239083..29332fa 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -1228,34 +1228,6 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, return 0; } -static struct eth_driver rte_virtio_pmd = { - { - .name = "rte_virtio_pmd", - .id_table = pci_id_virtio_map, - }, - .eth_dev_init = eth_virtio_dev_init, - .dev_private_size = sizeof(struct virtio_hw), -}; - -/* - * Driver initialization routine. - * Invoked once at EAL init time. - * Register itself as the [Poll Mode] Driver of PCI virtio devices. - * Returns 0 on success. - */ -static int -rte_virtio_pmd_init(const char *name __rte_unused, - const char *param __rte_unused) -{ - if (rte_eal_iopl_init() != 0) { - PMD_INIT_LOG(ERR, "IOPL call failed - cannot use virtio PMD"); - return -1; - } - - rte_eth_driver_register(&rte_virtio_pmd); - return 0; -} - /* * Only 1 queue is supported, no queue release related operation */ @@ -1484,6 +1456,49 @@ __rte_unused uint8_t is_rx) return 0; } +/* + * Early init function, this is needed so that iopl() on linux is done before + * rte_eal_init (since it creates other threads that must inherit from the one + * that calls rte_eal_init). + */ +static void __attribute__((constructor, used)) +rte_virtio_early_init(void) +{ + /* return value is checked at pmd init time, no need to check here, see + * below. */ + rte_eal_iopl_init(); +} + +static struct eth_driver rte_virtio_pmd = { + { + .name = "rte_virtio_pmd", + .id_table = pci_id_virtio_map, + }, + .eth_dev_init = eth_virtio_dev_init, + .dev_private_size = sizeof(struct virtio_hw), +}; + +/* + * Driver initialization routine. + * Invoked once at EAL init time. + * Register itself as the [Poll Mode] Driver of PCI virtio devices. + * Returns 0 on success. + */ +static int +rte_virtio_pmd_init(const char *name __rte_unused, + const char *param __rte_unused) +{ + /* rte_eal_iopl_init() is already called by rte_virtio_early_init(). + * Call it again here, to be sure we did get the io level we wanted. */ + if (rte_eal_iopl_init() != 0) { + PMD_INIT_LOG(ERR, "IOPL call failed - cannot use virtio PMD"); + return -1; + } + + rte_eth_driver_register(&rte_virtio_pmd); + return 0; +} + static struct rte_driver rte_virtio_driver = { .type = PMD_PDEV, .init = rte_virtio_pmd_init,