README.virtio 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. # SPDX-License-Identifier: GPL-2.0+
  2. #
  3. # Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
  4. VirtIO Support
  5. ==============
  6. This document describes the information about U-Boot support for VirtIO [1]
  7. devices, including supported boards, build instructions, driver details etc.
  8. What's VirtIO?
  9. --------------
  10. VirtIO is a virtualization standard for network and disk device drivers where
  11. just the guest's device driver "knows" it is running in a virtual environment,
  12. and cooperates with the hypervisor. This enables guests to get high performance
  13. network and disk operations, and gives most of the performance benefits of
  14. paravirtualization. In the U-Boot case, the guest is U-Boot itself, while the
  15. virtual environment are normally QEMU [2] targets like ARM, RISC-V and x86.
  16. Status
  17. ------
  18. VirtIO can use various different buses, aka transports as described in the
  19. spec. While VirtIO devices are commonly implemented as PCI devices on x86,
  20. embedded devices models like ARM/RISC-V, which does not normally come with
  21. PCI support might use simple memory mapped device (MMIO) instead of the PCI
  22. device. The memory mapped virtio device behaviour is based on the PCI device
  23. specification. Therefore most operations including device initialization,
  24. queues configuration and buffer transfers are nearly identical. Both MMIO
  25. and PCI transport options are supported in U-Boot.
  26. The VirtIO spec defines a lots of VirtIO device types, however at present only
  27. network and block device, the most two commonly used devices, are supported.
  28. The following QEMU targets are supported.
  29. - qemu_arm_defconfig
  30. - qemu_arm64_defconfig
  31. - qemu-riscv32_defconfig
  32. - qemu-riscv64_defconfig
  33. - qemu-x86_defconfig
  34. - qemu-x86_64_defconfig
  35. Note ARM and RISC-V targets are configured with VirtIO MMIO transport driver,
  36. and on x86 it's the PCI transport driver.
  37. Build Instructions
  38. ------------------
  39. Building U-Boot for pre-configured QEMU targets is no different from others.
  40. For example, we can do the following with the CROSS_COMPILE environment
  41. variable being properly set to a working toolchain for ARM:
  42. $ make qemu_arm_defconfig
  43. $ make
  44. You can even create a QEMU ARM target with VirtIO devices showing up on both
  45. MMIO and PCI buses. In this case, you can enable the PCI transport driver
  46. from 'make menuconfig':
  47. Device Drivers --->
  48. ...
  49. VirtIO Drivers --->
  50. ...
  51. [*] PCI driver for virtio devices
  52. Other drivers are at the same location and can be tuned to suit the needs.
  53. Requirements
  54. ------------
  55. It is required that QEMU v2.5.0+ should be used to test U-Boot VirtIO support
  56. on QEMU ARM and x86, and v2.12.0+ on QEMU RISC-V.
  57. Testing
  58. -------
  59. The following QEMU command line is used to get U-Boot up and running with
  60. VirtIO net and block devices on ARM.
  61. $ qemu-system-arm -nographic -machine virt -bios u-boot.bin \
  62. -netdev tap,ifname=tap0,id=net0 \
  63. -device virtio-net-device,netdev=net0 \
  64. -drive if=none,file=test.img,format=raw,id=hd0 \
  65. -device virtio-blk-device,drive=hd0
  66. On x86, command is slightly different to create PCI VirtIO devices.
  67. $ qemu-system-i386 -nographic -bios u-boot.rom \
  68. -netdev tap,ifname=tap0,id=net0 \
  69. -device virtio-net-pci,netdev=net0 \
  70. -drive if=none,file=test.img,format=raw,id=hd0 \
  71. -device virtio-blk-pci,drive=hd0
  72. Additional net and block devices can be created by appending more '-device'
  73. parameters. It is also possible to specify both MMIO and PCI VirtIO devices.
  74. For example, the following commnad creates 3 VirtIO devices, with 1 on MMIO
  75. and 2 on PCI bus.
  76. $ qemu-system-arm -nographic -machine virt -bios u-boot.bin \
  77. -netdev tap,ifname=tap0,id=net0 \
  78. -device virtio-net-pci,netdev=net0 \
  79. -drive if=none,file=test0.img,format=raw,id=hd0 \
  80. -device virtio-blk-device,drive=hd0 \
  81. -drive if=none,file=test1.img,format=raw,id=hd1 \
  82. -device virtio-blk-pci,drive=hd1
  83. By default QEMU creates VirtIO legacy devices by default. To create non-legacy
  84. (aka modern) devices, pass additional device property/value pairs like below:
  85. $ qemu-system-i386 -nographic -bios u-boot.rom \
  86. -netdev tap,ifname=tap0,id=net0 \
  87. -device virtio-net-pci,netdev=net0,disable-legacy=true,disable-modern=false \
  88. -drive if=none,file=test.img,format=raw,id=hd0 \
  89. -device virtio-blk-pci,drive=hd0,disable-legacy=true,disable-modern=false
  90. A 'virtio' command is provided in U-Boot shell.
  91. => virtio
  92. virtio - virtio block devices sub-system
  93. Usage:
  94. virtio scan - initialize virtio bus
  95. virtio info - show all available virtio block devices
  96. virtio device [dev] - show or set current virtio block device
  97. virtio part [dev] - print partition table of one or all virtio block devices
  98. virtio read addr blk# cnt - read `cnt' blocks starting at block
  99. `blk#' to memory address `addr'
  100. virtio write addr blk# cnt - write `cnt' blocks starting at block
  101. `blk#' from memory address `addr'
  102. To probe all the VirtIO devices, type:
  103. => virtio scan
  104. Then we can show the connected block device details by:
  105. => virtio info
  106. Device 0: QEMU VirtIO Block Device
  107. Type: Hard Disk
  108. Capacity: 4096.0 MB = 4.0 GB (8388608 x 512)
  109. And list the directories and files on the disk by:
  110. => ls virtio 0 /
  111. <DIR> 4096 .
  112. <DIR> 4096 ..
  113. <DIR> 16384 lost+found
  114. <DIR> 4096 dev
  115. <DIR> 4096 proc
  116. <DIR> 4096 sys
  117. <DIR> 4096 var
  118. <DIR> 4096 etc
  119. <DIR> 4096 usr
  120. <SYM> 7 bin
  121. <SYM> 8 sbin
  122. <SYM> 7 lib
  123. <SYM> 9 lib64
  124. <DIR> 4096 run
  125. <DIR> 4096 boot
  126. <DIR> 4096 home
  127. <DIR> 4096 media
  128. <DIR> 4096 mnt
  129. <DIR> 4096 opt
  130. <DIR> 4096 root
  131. <DIR> 4096 srv
  132. <DIR> 4096 tmp
  133. 0 .autorelabel
  134. Driver Internals
  135. ----------------
  136. There are 3 level of drivers in the VirtIO driver family.
  137. +---------------------------------------+
  138. | virtio device drivers |
  139. | +-------------+ +------------+ |
  140. | | virtio-net | | virtio-blk | |
  141. | +-------------+ +------------+ |
  142. +---------------------------------------+
  143. +---------------------------------------+
  144. | virtio transport drivers |
  145. | +-------------+ +------------+ |
  146. | | virtio-mmio | | virtio-pci | |
  147. | +-------------+ +------------+ |
  148. +---------------------------------------+
  149. +----------------------+
  150. | virtio uclass driver |
  151. +----------------------+
  152. The root one is the virtio uclass driver (virtio-uclass.c), which does lots of
  153. common stuff for the transport drivers (virtio_mmio.c, virtio_pci.c). The real
  154. virtio device is discovered in the transport driver's probe() method, and its
  155. device ID is saved in the virtio uclass's private data of the transport device.
  156. Then in the virtio uclass's post_probe() method, the real virtio device driver
  157. (virtio_net.c, virtio_blk.c) is bound if there is a match on the device ID.
  158. The child_post_bind(), child_pre_probe() and child_post_probe() methods of the
  159. virtio uclass driver help bring the virtio device driver online. They do things
  160. like acknowledging device, feature negotiation, etc, which are really common
  161. for all virtio devices.
  162. The transport drivers provide a set of ops (struct dm_virtio_ops) for the real
  163. virtio device driver to call. These ops APIs's parameter is designed to remind
  164. the caller to pass the correct 'struct udevice' id of the virtio device, eg:
  165. int virtio_get_status(struct udevice *vdev, u8 *status)
  166. So the parameter 'vdev' indicates the device should be the real virtio device.
  167. But we also have an API like:
  168. struct virtqueue *vring_create_virtqueue(unsigned int index, unsigned int num,
  169. unsigned int vring_align,
  170. struct udevice *udev)
  171. Here the parameter 'udev' indicates the device should be the transport device.
  172. Similar naming is applied in other functions that are even not APIs, eg:
  173. static int virtio_uclass_post_probe(struct udevice *udev)
  174. static int virtio_uclass_child_pre_probe(struct udevice *vdev)
  175. So it's easy to tell which device these functions are operating on.
  176. Development Flow
  177. ----------------
  178. At present only VirtIO network card (device ID 1) and block device (device
  179. ID 2) are supported. If you want to develop new driver for new devices,
  180. please follow the guideline below.
  181. 1. add new device ID in virtio.h
  182. #define VIRTIO_ID_XXX X
  183. 2. update VIRTIO_ID_MAX_NUM to be the largest device ID plus 1
  184. 3. add new driver name string in virtio.h
  185. #define VIRTIO_XXX_DRV_NAME "virtio-xxx"
  186. 4. create a new driver with name set to the name string above
  187. U_BOOT_DRIVER(virtio_xxx) = {
  188. .name = VIRTIO_XXX_DRV_NAME,
  189. ...
  190. .remove = virtio_reset,
  191. .flags = DM_FLAG_ACTIVE_DMA,
  192. }
  193. Note the driver needs to provide the remove method and normally this can be
  194. hooked to virtio_reset(). The driver flags should contain DM_FLAG_ACTIVE_DMA
  195. for the remove method to be called before jumping to OS.
  196. 5. provide bind() method in the driver, where virtio_driver_features_init()
  197. should be called for driver to negotiate feature support with the device.
  198. 6. do funny stuff with the driver
  199. References
  200. ----------
  201. [1] http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.pdf
  202. [2] https://www.qemu.org