Skip to content

Latest commit

 

History

History
335 lines (243 loc) · 18.3 KB

README_4_Devices.md

File metadata and controls

335 lines (243 loc) · 18.3 KB

Previous Part 3. Configurations, Machines CPUs and more

Devices

Usage (type -device help to get a list of all devices)

$ qemu-system-x86_64 -device [target],[option]

Specifies the device to be used in the machine, along with any additional options. QEMU provides virtual/emulated hardware devices to the guest machine, allowing it to interact with the external world, just like if it were running on real hardware. 1.

The sentence above is taken almost as is from the QEMU Wikibooks page.

Just like in a real hardware, QEMU machines can also have external devices connected to them. For example, USB, Network Card, VGA, Sound Card and many more! There are many options that you can choose here, and each have it's own options as well. It would be a VERY LONG GUIDE if I were to explain each of them here. For that, I will explain only the most used ones here.

Useful Information You can add help as an option to any -device targets to get a list of all available options! It is a great way to learn more about that device. Here's an example:

$ qemu-system-x86_64 -device sd-card,help

# Output
> sd-card options:
>   drive=<str>            - Node name or ID of a block device to use as a backend
>   spec_version=<uint8>   -  (default: 2)
>   spi=<bool>             -  (default: false)

VirtIO

Virtual Input/Output, virtIO, devices are special type of devices that are tailored for virtual machines. Formally, virtIO is not a device but a specification. 2 The main purpose here is to simplify the virtual devices, and naturally making them efficient and high-performant. There are many devices specified within virtIO specification. We simply call them virtIO devices.

Here are some of the most commonly used ones:

  • Networking virto-net 3
  • Storage virtio-scsi 4
  • Block virto-blk 5
  • GPU virtio-gpu 6
  • Console virtio-console 7
  • Serial virto-serial 8

Unlike other devices in QEMU (Intel E1000 Network Card), the above virtIO devices are very minimal. This is because most of the operations like setup and maintenance is handled by the host. This makes virtIO very simple and straightforward to use within the guest.

virtIO devices are pretty cool. If you are interested about how they work and implemented check out Oracle's Introduction to VirtIO. For now, all we need to know is that they are special devices designed to be used in virtual machines.

Each virtIO device deserve its own writing. I will only talk about some of them here. If you want to learn more, check out the references linked in the above list.

Input Devices

Input devices in QEMU refer to the devices that allow users to interact with the guest machine by providing input. These devices include keyboards, mouse, and other input peripherals. Here's some of the most commonly used input devices.

  • usb-kbd: An emulated generic USB keyboard.
  • usb-mouse: An emulated generic USB mouse.
  • usb-serial: An emulated USB serial device for serial communication.
  • usb-tablet: An emulated USB tablet for touch inputs. (pretty cool imo)
  • virtio-keyboard: Virtual keyboard that uses the VirtIO specification.
  • virtio-mouse: Virtual mouse that uses the VirtIO specification.
  • virtio-serial: Virtual serial communication that uses the VirtIO specification.
  • virtio-tablet: Virtual table for touch inputs that uses the VirtIO specification.

There are many more Input devices that can be specified in QEMU. But most of the time you will only be using the ones above. The importing to note here is the difference between the usb-* and virtio-* devices. Essentially, both achieves the same thing. The only difference is their implementation (guest driver and host device).

If you want an efficient input device, then simply use virtio-* devices. However, if you really need usb-* devices (when developing/testing drivers), then use that as you wish.

An example usage:

$ qemu-system-x86_64 ... -device usb-kbd -device usb-mouse ...

To learn more about an Input device use -device [target],help:

$ qemu-system-x86_64 -device usb-kbd,help

# Output
> usb-kbd options:
>  attached=<bool>
>  display=<str>
>  msos-desc=<bool>       - on/off (default: true)
>  pcap=<str>
>  port=<str>
>  serial=<str>
>  usb_version=<uint32>   -  (default: 2)

Network Devices

Network devices in QEMU provides the guest machine with a Network Interface Controller (NIC).9. These NIC devices enables the guest machine to connect to various types of networks. Refer to the Networking for more information on how Networking is handled within QEMU.

Here are some of the most commonly used network devices:

  • e1000: Emulates an Intel 8254x-based Gigabit Ethernet NIC.
  • rtl8139: Emulates a Realtek RTL8139-based Ethernet NIC. (very popular)
  • virtio-net: A virtual NIC using the VirtIO specification.
  • usb-net: Emulates a generic USB NIC.

These network devices offer different network connectivity options for the guest machine. You can choose the appropriate device based on your requirements and needs. Generally rtl8139 and e1000 is used when developing/testing Ethernet drivers. And virtio-net is used [heavily] within virtual machines and various cloud solutions.

An example usage:

$ qemu-system-x86_64 ... -device rtl8139,mac=52:54:00:12:34:56,netdev=mynetdev ...

The netdev=[name] is very important in here. Please, refer to Networking.

To learn more about a Network device use -device [target],help:

$ qemu-system-x86_64 -device rtl8139,help

# Output
> rtl8139 options:
>  acpi-index=<uint32>    -  (default: 0)
>  addr=<int32>           - Slot and optional function number, example: 06.0 or 06 (default: -1)
> ...
>  mac=<str>              - Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56
> ...
>  netdev=<str>           - ID of a netdev to use as a backend
>  ...

Storage Devices

Storage devices in QEMU facilitate the storage and retrieval of data between the guest and host machine. They allow the guest machine to access and manage storage resources (like a real-world storage device).

Here are some of the most commonly used storage devices in QEMU:

  • scsi-hd: Emulates a SCSI disk device (SSD/HDD).
  • scsi-cd: Emulates a SCSI CD/DVD device.
  • ide-hd: Emulates an IDE hard disk device (SSD/HDD).
  • ide-cd: Emulates an IDE CD/DVD device.
  • nvme: Emulates an NVMe (Non-Volatile Memory Express) storage device.
  • usb-storage: Emulates a generic USB storage device.
  • sd-card: Emulates a generic SD card device.
  • virtio-blk: A virtual block device that uses VirtIO specification.
  • virtio-scsi: A virtual storage device uses the SCSI protocol and the VirtIO specification.

You might be confused, because we already have -drive to give storage access to the guest machine (Refer to Disks). Why do we have another way to add a storage device? You are totally right, the difference between a -device [storage_dev] and a -drive is somewhat blurry. But they DO have different purposes.

The storage devices (-device [storage_dev]) gives the guest machine just an interface. The storage part of if does not exist until you specify one using the -drive. This might be useful when developing/testing a driver. Now, let's go over an example to understand this better.

Assume that I have a disk image called disk0.qcow2. I have two options to expose that to my QEMU machine.

  • Using only -drive: The simplest way. Just do ... -drive file=disk0.qcow2,format=qcow2,if=virtio
  • Using both -device and -drive: The more controlled way. Do -device virtio-blk,drive=mydrive and -drive file=disk0.qcow2,format=qcow2,id=mydrive

As you can see I can use -device to add a Storage device and ADDITIONALLY use -drive to expose my disk image using the drive identifier. However, I can choose NOT to use -device and simply use -drive by specifying the if=[target]. With QEMU, you are free to choose whichever you want!

In other words, -device specifies the device model rather than directly exposing a disk image.

An example usage:

$ qemu-system-x86_64 ... -device nvme,drive=my-ubuntu-drive ...

To learn more about a Storage device use -device [target],help:

$ qemu-system-x86_64 -device virtio-blk,help

# Output
> virtio-blk options:
>  ...
>  drive=<str>                - Node name or ID of a block device to use as a backend
>  ...
>  physical_block_size=<size> - A power of two between 512 B and 2 MiB (default: 0)
>  vectors=<uint32>           -  (default: 4294967295)
>  ...

Display Devices

Display devices in QEMU handle the graphical output of the guest machine. When configured with a display device, a window is shown on the host machine. Thru that window, the guest machine can display graphics, and if possible, accept inputs such as mouse clicks and touch inputs.

QEMU makes use of host's windowing system when displaying GUI elements. Win32 on Windows10, AppKit on macOS11 and GTK on GNU/Linux12.

By default, a QEMU machine is launched with a qxl-vga display device. However, you can disable this via configurations like -nographic. This way you will be disabling the display and other host GUI elements!

Disabling the display might be useful if you don't intent to interact with the guest via a GUI (e.g. mouse clicks). For example, servers and headless computers choose to use SSH and/or VNC instead of an actual display device.

Here's some of the most commonly used Displays:

  • vga: Emulates a very simple and generic VGA display.
  • bochs-display: Emulates a generic VGA display. Similar to vga.
  • virtio-vga: A virtual VGA display device using the VirtIO specification.
  • virtio-gpu: A virtual GPU display device using the VirtIO specification. Similar to virtio-vga.
  • qxl-vga: Emulates a QXL VGA display. Provides accelerated graphics capabilities for virtual machines. Good for Windows.
  • ramfb: Emulates a framebuffer device backed by host RAM. Provides a simple display output.

Most of the time you will be fine using the default display device, qxl-vga. If your intention is to use QEMU to do some 'heavy' GPU stuff (DirectX, Vulkan, Tensor), just don't. That's why other emulation/virtualization services exist (e.g. Parallels, Crossover,VMWare Workstation). Maybe in the future QEMU will be mature enough for this type of stuff.

There are some amazing people out there working on 3D acceleration and decent GPU support to QEMU. I highly suggest you to check them out! Mesa3D VirGL, ArchLinux Guest Graphics Acceleration, Kraxel Display Devices in QEMU

An example usage:

$ qemu-system-x86_64 ... -device virtio-gpu,xres=1920,yres=1080 ...

To learn more about a Display device use -device [target],help:

$ qemu-system-x86_64 -device virtio-gpu,help

# Output
> virtio-gpu-pci options:
>  acpi-index=<uint32>    -  (default: 0)
>  addr=<int32>           - Slot and optional function number, example: 06.0 or 06 (default: -1)
>  ...
>  virtio-backend=<child<virtio-gpu-device>>
>  virtio-pci-bus-master-bug-migration=<bool> - on/off (default: false)
>  ...
>  xres=<uint32>          -  (default: 1280)
>  yres=<uint32>          -  (default: 800)

Sound Devices

Sound devices in QEMU handle the audio output and input of the guest machine. These are basically Sound cards that you connect to the guest machine. By default, QEMU chooses the good-old ac97, which emulates the AC'97 audio controller.13

Alternatively, you can use the hda (Intel High Definition Audio) sound device. This provides support for modern audio controllers and improved audio quality compared to ac97.14 So, you probably want to use hda all the time. Unless, of course, you want to support legacy devices or just want to do some developing/testing.

There are also many more Sound devices that QEMU can emulate.15 Here's a list of the most used ones:

  • ac97: Emulates the AC'97 audio controller.
  • intel-hda: Emulates the Intel High Definition Audio (HDA) controller.
  • hda-output: Represents a HDA output device. Emulates a playback-only audio device using the HDA controller.
  • hda-micro: Represents a HDA input device. Emulates a recording-only audio device using the HDA controller.
  • hda-duplex: Represents a HDA I/O device. Emulates both playback and recording audio device using the HDA controller.
  • ich9-intel: Emulates the Intel ICH9 HD Audio controller.
  • usb-audio: Represents a USB audio device. Emulates a USB audio controller, allowing both audio playback and recording.

Although, there seems to be many options to choose from, you rarely use anything other than hda. It is the most common one both in real-world and in QEMU as well. You might be confused as to why there is intel-hda AND hda-*. The intel-hda in and on itself does NOT provide neither audio playback or recording. It is just an audio controller. You MUST add hda-output, hda-micro or hda-duplex in order to get audio working on your QEMU machine.

My recommendation is to just use intel-hda AND hda-duplex, unless you want to develop/test something else. Most guest OS's has hda drivers out-of-box (e.g. Windows, GNU/Linux).16

An example usage:

$ qemu-system-x86_64 ... -device intel-hda -device hda-duplex ...

To learn more about a Sound device use -device [target],help:

$ qemu-system-x86_64 -device hda-duplex,help

# Output
> hda-duplex options:
>  audiodev=<str>         - ID of an audiodev to use as a backend
>  cad=<uint32>           -  (default: 4294967295)
>  debug=<uint32>         -  (default: 0)
>  mixer=<bool>           -  (default: true)
>  use-timer=<bool>       -  (default: true)

USB Devices

Universel Serial Bus, USB, devices in QEMU is used for all kinds of purposes. QEMU can emulate a PCI UHCI, OHCI, EHCI or XHCI USB controller.17 How these devices can be used is up to the guest machine.

So far, we have seen some USB devices such as usb-kbd, usb-storage or usb-audio. These are all your typical USB devices, used for different purposes. There are many more USB devices that QEMU can also emulate. Here's some of the most popular ones.

  • usb-host: Allows you to pass through a USB device connected from host to guest. 18
  • usb-hub: Emulates a generic USB hub with multiple USB ports. 19
  • nec-usb-xchi: Emulates an NEC USB eXtensible Host Controller Interface (xHCI) controller. Supports USB 3.0. 2021
  • usb-ehci: Emulates a USB 2.0 Enhanced Host Controller Interface (EHCI) controller. 22
  • usb-storage: Represents a USB storage device (e.g. flash drive, external hard drive).
  • usb-mtp: Emulates a USB Media Transfer Protocol (MTP) device. 23
  • usb-net: Emulates a generic USB network adapter (e.g. Android/iPhone network sharing /w USB).24
  • usb-kbd: Refer to Input Devices
  • usb-mouse: Refer to Input Devices
  • usb-serial: Refer to Input Devices
  • usb-wacom-tablet: Emulates a USB Wacom tablet device. 25
  • usb-audio: Refer to Sound Devices

As you can see, there are many USB device that QEMU can emulate. It is pretty amazing IMO! You can learn more about USB emulation in QEMU from it's official documentation page: USB emulation.

The USB pass through (usb-host) is an extremely useful feature of QEMU. I have personally used it to pass my Crazyflie 2.1 drone's USB dongle from the macOS host machine to Ubuntu guest machine!

You can learn more about it here on KVM - Assigning Host USB to Guest VM

An example usage:

$ qemu-system-x86_64 ... -device usb-host,hostbus=3,hostport=10 ...

To learn more about an USB device use -device [target],help:

$ qemu-system-x86_64 -device usb-hub,help

# Output
> usb-hub options:
>  attached=<bool>
>  msos-desc=<bool>       - on/off (default: true)
>  pcap=<str>
>  port-power=<bool>      -  (default: false)
>  port=<str>
>  ports=<uint32>         -  (default: 8)
>  serial=<str>

Next Part 5. UEFI, BIOS and OVMF

Footnotes

  1. https://en.wikibooks.org/wiki/QEMU/Devices

  2. https://www.oasis-open.org/committees/virtio/

  3. https://projectacrn.github.io/latest/developer-guides/hld/virtio-net.html

  4. https://www.qemu.org/2021/01/19/virtio-blk-scsi-configuration/

  5. https://projectacrn.github.io/latest/developer-guides/hld/virtio-blk.html

  6. https://docs.oasis-open.org/virtio/virtio/v1.1/cs01/virtio-v1.1-cs01.html#x1-3200007

  7. https://projectacrn.github.io/latest/developer-guides/hld/virtio-console.html

  8. https://fedoraproject.org/wiki/Features/VirtioSerial

  9. https://en.wikipedia.org/wiki/Network_interface_controller

  10. https://learn.microsoft.com/en-us/windows/win32/apiindex/windows-api-list#user-interface

  11. https://developer.apple.com/documentation/appkit

  12. https://www.gtk.org

  13. https://en.wikipedia.org/wiki/AC%2797

  14. https://en.wikipedia.org/wiki/Intel_High_Definition_Audio

  15. https://computernewb.com/wiki/QEMU/Devices/Sound_cards

  16. https://github.com/torvalds/linux/blob/master/sound/pci/hda/hda_intel.c

  17. https://qemu-project.gitlab.io/qemu/system/devices/usb.html

  18. https://www.linux-kvm.org/page/USB_Host_Device_Assigned_to_Guest

  19. https://www.kraxel.org/blog/2018/08/qemu-usb-tips/

  20. https://en.wikipedia.org/wiki/NEC

  21. https://en.wikipedia.org/wiki/Extensible_Host_Controller_Interface

  22. http://www.intel.com/content/www/us/en/io/universal-serial-bus/ehci-specification.html

  23. https://en.wikipedia.org/wiki/Media_Transfer_Protocol

  24. https://en.wikipedia.org/wiki/Ethernet_over_USB

  25. https://www.wacom.com/en-us