From patchwork Sun Sep 23 13:42:25 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bin Meng X-Patchwork-Id: 973695 X-Patchwork-Delegate: sjg@chromium.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.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="aiE+ZUgC"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 42J80W5lnwz9sBW for ; Sun, 23 Sep 2018 23:52:27 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 6EC71C21DAF; Sun, 23 Sep 2018 13:48:03 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 2B68CC21F41; Sun, 23 Sep 2018 13:40:14 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 1FD9CC21F1F; Sun, 23 Sep 2018 13:38:50 +0000 (UTC) Received: from mail-pl1-f196.google.com (mail-pl1-f196.google.com [209.85.214.196]) by lists.denx.de (Postfix) with ESMTPS id 16328C21E16 for ; Sun, 23 Sep 2018 13:38:46 +0000 (UTC) Received: by mail-pl1-f196.google.com with SMTP id b12-v6so7962228plr.8 for ; Sun, 23 Sep 2018 06:38:46 -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=or8FXVAsoAPiiOUPlyxj1QL0kW+if+qLS3sh4gwCnVA=; b=aiE+ZUgCMbRqkgxybitBc/V/Mi3YrUBMOIPbnlYoWzjNXcrh5PLq4KCO33gKS7LK0p JfmJ9OQX0cx2zcTYR2gwF63Jese2n1/NbEVvV73uWxtL2mJXft8XA/HG3L0BnA1uSNVo YJU7FLAa/Y5FZSNJMgZ4MDQRUAqx26d27Oq++gyJ81v8GGPhq1tbEjyii1DQEqnF0GbA Vk+vu8YTvIn5X+xbfzEsYgzpTith/AIAevYnWH59CBD0dLX8xjNmrfQkEy/7OlMuM9c0 aBHaGLhLJ4B5HgWDEpcXFuDO2kbLZ6QZRWxeVkwzL83mFyh32Q48s30LloZcz30JXabL N1mQ== 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=or8FXVAsoAPiiOUPlyxj1QL0kW+if+qLS3sh4gwCnVA=; b=LDAL9CiljBq2tOKSd9iQiK0rr7wA4WVnzb5AbY6rb0SHRGpEZ2dJ4ys6UWqTJ8sDsC JRHvBA+Y+rtaNCkLhh3uweDwDi2oJb4tIzUDBmcjCc5wLsmmUPk2am3wSOK+kv08HhvV 98JAUI5OJlBhHA7oxwxU63AXaItZVzrG7EqZZP8wVWN5/6U5NIhBNApEOdWbfoXu9Xmw jM1ZFN0MCY10fZ161sy0VrVTUhTz8c+3tARLCF7trBISzdBbr12Ljav5QQQmewWxWxiy PexIrE5wxCrMzUex/3EKra7Kr6oB7DhU/TbBB5Ti3yCciBS1kB8fwpd8ZPpTzr/2OIEJ RU2A== X-Gm-Message-State: ABuFfohL9xWX70FMYQsvcSrCa4HwCzDrd1Yt6M0Ynle0KMlylMSOxN3u se/QF6AVmIhNWyl3IMtZBC5ks3zR X-Google-Smtp-Source: ACcGV6223tpGSBpJS5cnKAGdKcUFPybTBY4I+1iQETznOiQFfqWgI8H/P4UqXoQd1G23iTUcIpTwXQ== X-Received: by 2002:a17:902:b03:: with SMTP id 3-v6mr6875575plq.156.1537709924578; Sun, 23 Sep 2018 06:38:44 -0700 (PDT) Received: from ala-d2121-lx1.wrs.com (unknown-156-139.windriver.com. [147.11.156.139]) by smtp.gmail.com with ESMTPSA id b126-v6sm51286073pga.49.2018.09.23.06.38.43 (version=TLS1_1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 23 Sep 2018 06:38:43 -0700 (PDT) From: Bin Meng To: Simon Glass , U-Boot Mailing List Date: Sun, 23 Sep 2018 06:42:25 -0700 Message-Id: <1537710145-1888-28-git-send-email-bmeng.cn@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1537710145-1888-1-git-send-email-bmeng.cn@gmail.com> References: <1537710145-1888-1-git-send-email-bmeng.cn@gmail.com> Subject: [U-Boot] [PATCH 27/27] doc: Document virtio support X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Add REAME.virtio to describe the information about U-Boot support for VirtIO devices, including supported boards, build instructions, driver details etc. Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- doc/README.virtio | 247 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 doc/README.virtio diff --git a/doc/README.virtio b/doc/README.virtio new file mode 100644 index 0000000..ad58fe8 --- /dev/null +++ b/doc/README.virtio @@ -0,0 +1,247 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2018, Bin Meng + +VirtIO Support +============== + +This document describes the information about U-Boot support for VirtIO [1] +devices, including supported boards, build instructions, driver details etc. + +What's VirtIO? +-------------- +VirtIO is a virtualization standard for network and disk device drivers where +just the guest's device driver "knows" it is running in a virtual environment, +and cooperates with the hypervisor. This enables guests to get high performance +network and disk operations, and gives most of the performance benefits of +paravirtualization. In the U-Boot case, the guest is U-Boot itself, while the +virtual environment are normally QEMU [2] targets like ARM, RISC-V and x86. + +Status +------ +VirtIO can use various different buses, aka transports as described in the +spec. While VirtIO devices are commonly implemented as PCI devices on x86, +embedded devices models like ARM/RISC-V, which does not normally come with +PCI support might use simple memory mapped device (MMIO) instead of the PCI +device. The memory mapped virtio device behaviour is based on the PCI device +specification. Therefore most operations including device initialization, +queues configuration and buffer transfers are nearly identical. Both MMIO +and PCI transport options are supported in U-Boot. + +The VirtIO spec defines a lots of VirtIO device types, however at present only +network and block device, the most two commonly used devices, are supported. + +The following QEMU targets are supported. + + - qemu_arm_defconfig + - qemu_arm64_defconfig + - qemu-riscv32_defconfig + - qemu-riscv64_defconfig + - qemu-x86_defconfig + - qemu-x86_64_defconfig + +Note ARM and RISC-V targets are configured with VirtIO MMIO transport driver, +and on x86 it's the PCI transport driver. + +Build Instructions +------------------ +Building U-Boot for pre-configured QEMU targets is no different from others. +For example, we can do the following with the CROSS_COMPILE environment +variable being properly set to a working toolchain for ARM: + + $ make qemu_arm_defconfig + $ make + +You can even create a QEMU ARM target with VirtIO devices showing up on both +MMIO and PCI buses. In this case, you can enable the PCI transport driver +from 'make menuconfig': + +Device Drivers ---> + ... + VirtIO Drivers ---> + ... + [*] PCI driver for virtio devices + +Other drivers are at the same location and can be tuned to suit the needs. + +Requirements +------------ +It is required that QEMU v2.5.0+ should be used to test U-Boot VirtIO support +on QEMU ARM and x86, and v2.12.0+ on QEMU RISC-V. + +Testing +------- +The following QEMU command line is used to get U-Boot up and running with +VirtIO net and block devices on ARM. + + $ qemu-system-arm -nographic -machine virt -bios u-boot.bin \ + -netdev tap,ifname=tap0,id=net0 \ + -device virtio-net-device,netdev=net0 \ + -drive if=none,file=test.img,format=raw,id=hd0 \ + -device virtio-blk-device,drive=hd0 + +On x86, command is slightly different to create PCI VirtIO devices. + + $ qemu-system-i386 -nographic -bios u-boot.rom \ + -netdev tap,ifname=tap0,id=net0 \ + -device virtio-net-pci,netdev=net0 \ + -drive if=none,file=test.img,format=raw,id=hd0 \ + -device virtio-blk-pci,drive=hd0 + +Additional net and block devices can be created by appending more '-device' +parameters. It is also possible to specify both MMIO and PCI VirtIO devices. +For example, the following commnad creates 3 VirtIO devices, with 1 on MMIO +and 2 on PCI bus. + + $ qemu-system-arm -nographic -machine virt -bios u-boot.bin \ + -netdev tap,ifname=tap0,id=net0 \ + -device virtio-net-pci,netdev=net0 \ + -drive if=none,file=test0.img,format=raw,id=hd0 \ + -device virtio-blk-device,drive=hd0 \ + -drive if=none,file=test1.img,format=raw,id=hd1 \ + -device virtio-blk-pci,drive=hd1 + +By default QEMU creates VirtIO legacy devices by default. To create non-legacy +(aka modern) devices, pass additional device property/value pairs like below: + + $ qemu-system-i386 -nographic -bios u-boot.rom \ + -netdev tap,ifname=tap0,id=net0 \ + -device virtio-net-pci,netdev=net0,disable-legacy=true,disable-modern=false \ + -drive if=none,file=test.img,format=raw,id=hd0 \ + -device virtio-blk-pci,drive=hd0,disable-legacy=true,disable-modern=false + +A 'virtio' command is provided in U-Boot shell. + + => virtio + virtio - virtio block devices sub-system + + Usage: + virtio scan - initialize virtio bus + virtio info - show all available virtio block devices + virtio device [dev] - show or set current virtio block device + virtio part [dev] - print partition table of one or all virtio block devices + virtio read addr blk# cnt - read `cnt' blocks starting at block + `blk#' to memory address `addr' + virtio write addr blk# cnt - write `cnt' blocks starting at block + `blk#' from memory address `addr' + +To probe all the VirtIO devices, type: + + => virtio scan + +Then we can show the connected block device details by: + + => virtio info + Device 0: QEMU VirtIO Block Device + Type: Hard Disk + Capacity: 4096.0 MB = 4.0 GB (8388608 x 512) + +And list the directories and files on the disk by: + + => ls virtio 0 / + 4096 . + 4096 .. + 16384 lost+found + 4096 dev + 4096 proc + 4096 sys + 4096 var + 4096 etc + 4096 usr + 7 bin + 8 sbin + 7 lib + 9 lib64 + 4096 run + 4096 boot + 4096 home + 4096 media + 4096 mnt + 4096 opt + 4096 root + 4096 srv + 4096 tmp + 0 .autorelabel + +Driver Internals +---------------- +There are 3 level of drivers in the VirtIO driver family. + + +---------------------------------------+ + | virtio device drivers | + | +-------------+ +------------+ | + | | virtio-net | | virtio-blk | | + | +-------------+ +------------+ | + +---------------------------------------+ + +---------------------------------------+ + | virtio transport drivers | + | +-------------+ +------------+ | + | | virtio-mmio | | virtio-pci | | + | +-------------+ +------------+ | + +---------------------------------------+ + +----------------------+ + | virtio uclass driver | + +----------------------+ + +The root one is the virtio uclass driver (virtio-uclass.c), which does lots of +common stuff for the transport drivers (virtio_mmio.c, virtio_pci.c). The real +virtio device is discovered in the transport driver's probe() method, and its +device ID is saved in the virtio uclass's private data of the transport device. +Then in the virtio uclass's post_probe() method, the real virtio device driver +(virtio_net.c, virtio_blk.c) is bound if there is a match on the device ID. + +The child_post_bind(), child_pre_probe() and child_post_probe() methods of the +virtio uclass driver help bring the virtio device driver online. They do things +like acknowledging device, feature negotiation, etc, which are really common +for all virtio devices. + +The transport drivers provide a set of ops (struct dm_virtio_ops) for the real +virtio device driver to call. These ops APIs's parameter is designed to remind +the caller to pass the correct 'struct udevice' id of the virtio device, eg: + +int virtio_get_status(struct udevice *vdev, u8 *status) + +So the parameter 'vdev' indicates the device should be the real virtio device. +But we also have an API like: + +struct virtqueue *vring_create_virtqueue(unsigned int index, unsigned int num, + unsigned int vring_align, + struct udevice *udev) + +Here the parameter 'udev' indicates the device should be the transport device. +Similar naming is applied in other functions that are even not APIs, eg: + +static int virtio_uclass_post_probe(struct udevice *udev) +static int virtio_uclass_child_pre_probe(struct udevice *vdev) + +So it's easy to tell which device these functions are operating on. + +Development Flow +---------------- +At present only VirtIO network card (device ID 1) and block device (device +ID 2) are supported. If you want to develop new driver for new devices, +please follow the guideline below. + +1. add new device ID in virtio.h +#define VIRTIO_ID_XXX X + +2. update VIRTIO_ID_MAX_NUM to be the largest device ID plus 1 + +3. add new driver name string in virtio.h +#define VIRTIO_XXX_DRV_NAME "virtio-xxx" + +4. create a new driver with name set to the name string above +U_BOOT_DRIVER(virtio_xxx) = { + .name = VIRTIO_XXX_DRV_NAME, + ... +} + +5. provide bind() method in the driver, where virtio_driver_features_init() + should be called for driver to negotiate feature support with the device. + +6. do funny stuff with the driver + +References +---------- +[1] http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.pdf +[2] https://www.qemu.org