xref: /openbmc/qemu/docs/devel/virtio-backends.rst (revision eec398119fc6911d99412c37af06a6bc27871f85)
1*bcf317f8SAlex Bennée..
2*bcf317f8SAlex Bennée   Copyright (c) 2022, Linaro Limited
3*bcf317f8SAlex Bennée   Written by Alex Bennée
4*bcf317f8SAlex Bennée
5*bcf317f8SAlex BennéeWriting VirtIO backends for QEMU
6*bcf317f8SAlex Bennée================================
7*bcf317f8SAlex Bennée
8*bcf317f8SAlex BennéeThis document attempts to outline the information a developer needs to
9*bcf317f8SAlex Bennéeknow to write device emulations in QEMU. It is specifically focused on
10*bcf317f8SAlex Bennéeimplementing VirtIO devices. For VirtIO the frontend is the driver
11*bcf317f8SAlex Bennéerunning on the guest. The backend is the everything that QEMU needs to
12*bcf317f8SAlex Bennéedo to handle the emulation of the VirtIO device. This can be done
13*bcf317f8SAlex Bennéeentirely in QEMU, divided between QEMU and the kernel (vhost) or
14*bcf317f8SAlex Bennéehandled by a separate process which is configured by QEMU
15*bcf317f8SAlex Bennée(vhost-user).
16*bcf317f8SAlex Bennée
17*bcf317f8SAlex BennéeVirtIO Transports
18*bcf317f8SAlex Bennée-----------------
19*bcf317f8SAlex Bennée
20*bcf317f8SAlex BennéeVirtIO supports a number of different transports. While the details of
21*bcf317f8SAlex Bennéethe configuration and operation of the device will generally be the
22*bcf317f8SAlex Bennéesame QEMU represents them as different devices depending on the
23*bcf317f8SAlex Bennéetransport they use. For example -device virtio-foo represents the foo
24*bcf317f8SAlex Bennéedevice using mmio and -device virtio-foo-pci is the same class of
25*bcf317f8SAlex Bennéedevice using the PCI transport.
26*bcf317f8SAlex Bennée
27*bcf317f8SAlex BennéeUsing the QEMU Object Model (QOM)
28*bcf317f8SAlex Bennée---------------------------------
29*bcf317f8SAlex Bennée
30*bcf317f8SAlex BennéeGenerally all devices in QEMU are super classes of ``TYPE_DEVICE``
31*bcf317f8SAlex Bennéehowever VirtIO devices should be based on ``TYPE_VIRTIO_DEVICE`` which
32*bcf317f8SAlex Bennéeitself is derived from the base class. For example:
33*bcf317f8SAlex Bennée
34*bcf317f8SAlex Bennée.. code:: c
35*bcf317f8SAlex Bennée
36*bcf317f8SAlex Bennée  static const TypeInfo virtio_blk_info = {
37*bcf317f8SAlex Bennée      .name = TYPE_VIRTIO_BLK,
38*bcf317f8SAlex Bennée      .parent = TYPE_VIRTIO_DEVICE,
39*bcf317f8SAlex Bennée      .instance_size = sizeof(VirtIOBlock),
40*bcf317f8SAlex Bennée      .instance_init = virtio_blk_instance_init,
41*bcf317f8SAlex Bennée      .class_init = virtio_blk_class_init,
42*bcf317f8SAlex Bennée  };
43*bcf317f8SAlex Bennée
44*bcf317f8SAlex BennéeThe author may decide to have a more expansive class hierarchy to
45*bcf317f8SAlex Bennéesupport multiple device types. For example the Virtio GPU device:
46*bcf317f8SAlex Bennée
47*bcf317f8SAlex Bennée.. code:: c
48*bcf317f8SAlex Bennée
49*bcf317f8SAlex Bennée  static const TypeInfo virtio_gpu_base_info = {
50*bcf317f8SAlex Bennée      .name = TYPE_VIRTIO_GPU_BASE,
51*bcf317f8SAlex Bennée      .parent = TYPE_VIRTIO_DEVICE,
52*bcf317f8SAlex Bennée      .instance_size = sizeof(VirtIOGPUBase),
53*bcf317f8SAlex Bennée      .class_size = sizeof(VirtIOGPUBaseClass),
54*bcf317f8SAlex Bennée      .class_init = virtio_gpu_base_class_init,
55*bcf317f8SAlex Bennée      .abstract = true
56*bcf317f8SAlex Bennée  };
57*bcf317f8SAlex Bennée
58*bcf317f8SAlex Bennée  static const TypeInfo vhost_user_gpu_info = {
59*bcf317f8SAlex Bennée      .name = TYPE_VHOST_USER_GPU,
60*bcf317f8SAlex Bennée      .parent = TYPE_VIRTIO_GPU_BASE,
61*bcf317f8SAlex Bennée      .instance_size = sizeof(VhostUserGPU),
62*bcf317f8SAlex Bennée      .instance_init = vhost_user_gpu_instance_init,
63*bcf317f8SAlex Bennée      .instance_finalize = vhost_user_gpu_instance_finalize,
64*bcf317f8SAlex Bennée      .class_init = vhost_user_gpu_class_init,
65*bcf317f8SAlex Bennée  };
66*bcf317f8SAlex Bennée
67*bcf317f8SAlex Bennée  static const TypeInfo virtio_gpu_info = {
68*bcf317f8SAlex Bennée      .name = TYPE_VIRTIO_GPU,
69*bcf317f8SAlex Bennée      .parent = TYPE_VIRTIO_GPU_BASE,
70*bcf317f8SAlex Bennée      .instance_size = sizeof(VirtIOGPU),
71*bcf317f8SAlex Bennée      .class_size = sizeof(VirtIOGPUClass),
72*bcf317f8SAlex Bennée      .class_init = virtio_gpu_class_init,
73*bcf317f8SAlex Bennée  };
74*bcf317f8SAlex Bennée
75*bcf317f8SAlex Bennéedefines a base class for the VirtIO GPU and then specialises two
76*bcf317f8SAlex Bennéeversions, one for the internal implementation and the other for the
77*bcf317f8SAlex Bennéevhost-user version.
78*bcf317f8SAlex Bennée
79*bcf317f8SAlex BennéeVirtIOPCIProxy
80*bcf317f8SAlex Bennée^^^^^^^^^^^^^^
81*bcf317f8SAlex Bennée
82*bcf317f8SAlex Bennée[AJB: the following is supposition and welcomes more informed
83*bcf317f8SAlex Bennéeopinions]
84*bcf317f8SAlex Bennée
85*bcf317f8SAlex BennéeProbably due to legacy from the pre-QOM days PCI VirtIO devices don't
86*bcf317f8SAlex Bennéefollow the normal hierarchy. Instead the a standalone object is based
87*bcf317f8SAlex Bennéeon the VirtIOPCIProxy class and the specific VirtIO instance is
88*bcf317f8SAlex Bennéemanually instantiated:
89*bcf317f8SAlex Bennée
90*bcf317f8SAlex Bennée.. code:: c
91*bcf317f8SAlex Bennée
92*bcf317f8SAlex Bennée  /*
93*bcf317f8SAlex Bennée   * virtio-blk-pci: This extends VirtioPCIProxy.
94*bcf317f8SAlex Bennée   */
95*bcf317f8SAlex Bennée  #define TYPE_VIRTIO_BLK_PCI "virtio-blk-pci-base"
96*bcf317f8SAlex Bennée  DECLARE_INSTANCE_CHECKER(VirtIOBlkPCI, VIRTIO_BLK_PCI,
97*bcf317f8SAlex Bennée                           TYPE_VIRTIO_BLK_PCI)
98*bcf317f8SAlex Bennée
99*bcf317f8SAlex Bennée  struct VirtIOBlkPCI {
100*bcf317f8SAlex Bennée      VirtIOPCIProxy parent_obj;
101*bcf317f8SAlex Bennée      VirtIOBlock vdev;
102*bcf317f8SAlex Bennée  };
103*bcf317f8SAlex Bennée
104*bcf317f8SAlex Bennée  static Property virtio_blk_pci_properties[] = {
105*bcf317f8SAlex Bennée      DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0),
106*bcf317f8SAlex Bennée      DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
107*bcf317f8SAlex Bennée                      VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
108*bcf317f8SAlex Bennée      DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
109*bcf317f8SAlex Bennée                         DEV_NVECTORS_UNSPECIFIED),
110*bcf317f8SAlex Bennée      DEFINE_PROP_END_OF_LIST(),
111*bcf317f8SAlex Bennée  };
112*bcf317f8SAlex Bennée
113*bcf317f8SAlex Bennée  static void virtio_blk_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
114*bcf317f8SAlex Bennée  {
115*bcf317f8SAlex Bennée      VirtIOBlkPCI *dev = VIRTIO_BLK_PCI(vpci_dev);
116*bcf317f8SAlex Bennée      DeviceState *vdev = DEVICE(&dev->vdev);
117*bcf317f8SAlex Bennée
118*bcf317f8SAlex Bennée      ...
119*bcf317f8SAlex Bennée
120*bcf317f8SAlex Bennée      qdev_realize(vdev, BUS(&vpci_dev->bus), errp);
121*bcf317f8SAlex Bennée  }
122*bcf317f8SAlex Bennée
123*bcf317f8SAlex Bennée  static void virtio_blk_pci_class_init(ObjectClass *klass, void *data)
124*bcf317f8SAlex Bennée  {
125*bcf317f8SAlex Bennée      DeviceClass *dc = DEVICE_CLASS(klass);
126*bcf317f8SAlex Bennée      VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
127*bcf317f8SAlex Bennée      PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
128*bcf317f8SAlex Bennée
129*bcf317f8SAlex Bennée      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
130*bcf317f8SAlex Bennée      device_class_set_props(dc, virtio_blk_pci_properties);
131*bcf317f8SAlex Bennée      k->realize = virtio_blk_pci_realize;
132*bcf317f8SAlex Bennée      pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
133*bcf317f8SAlex Bennée      pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_BLOCK;
134*bcf317f8SAlex Bennée      pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
135*bcf317f8SAlex Bennée      pcidev_k->class_id = PCI_CLASS_STORAGE_SCSI;
136*bcf317f8SAlex Bennée  }
137*bcf317f8SAlex Bennée
138*bcf317f8SAlex Bennée  static void virtio_blk_pci_instance_init(Object *obj)
139*bcf317f8SAlex Bennée  {
140*bcf317f8SAlex Bennée      VirtIOBlkPCI *dev = VIRTIO_BLK_PCI(obj);
141*bcf317f8SAlex Bennée
142*bcf317f8SAlex Bennée      virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
143*bcf317f8SAlex Bennée                                  TYPE_VIRTIO_BLK);
144*bcf317f8SAlex Bennée      object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
145*bcf317f8SAlex Bennée                                "bootindex");
146*bcf317f8SAlex Bennée  }
147*bcf317f8SAlex Bennée
148*bcf317f8SAlex Bennée  static const VirtioPCIDeviceTypeInfo virtio_blk_pci_info = {
149*bcf317f8SAlex Bennée      .base_name              = TYPE_VIRTIO_BLK_PCI,
150*bcf317f8SAlex Bennée      .generic_name           = "virtio-blk-pci",
151*bcf317f8SAlex Bennée      .transitional_name      = "virtio-blk-pci-transitional",
152*bcf317f8SAlex Bennée      .non_transitional_name  = "virtio-blk-pci-non-transitional",
153*bcf317f8SAlex Bennée      .instance_size = sizeof(VirtIOBlkPCI),
154*bcf317f8SAlex Bennée      .instance_init = virtio_blk_pci_instance_init,
155*bcf317f8SAlex Bennée      .class_init    = virtio_blk_pci_class_init,
156*bcf317f8SAlex Bennée  };
157*bcf317f8SAlex Bennée
158*bcf317f8SAlex BennéeHere you can see the instance_init has to manually instantiate the
159*bcf317f8SAlex Bennéeunderlying ``TYPE_VIRTIO_BLOCK`` object and link an alias for one of
160*bcf317f8SAlex Bennéeit's properties to the PCI device.
161*bcf317f8SAlex Bennée
162*bcf317f8SAlex Bennée
163*bcf317f8SAlex BennéeBack End Implementations
164*bcf317f8SAlex Bennée------------------------
165*bcf317f8SAlex Bennée
166*bcf317f8SAlex BennéeThere are a number of places where the implementation of the backend
167*bcf317f8SAlex Bennéecan be done:
168*bcf317f8SAlex Bennée
169*bcf317f8SAlex Bennée* in QEMU itself
170*bcf317f8SAlex Bennée* in the host kernel (a.k.a vhost)
171*bcf317f8SAlex Bennée* in a separate process (a.k.a. vhost-user)
172*bcf317f8SAlex Bennée
173*bcf317f8SAlex Bennéevhost_ops vs TYPE_VHOST_USER_BACKEND
174*bcf317f8SAlex Bennée^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
175*bcf317f8SAlex Bennée
176*bcf317f8SAlex BennéeThere are two choices to how to implement vhost code. Most of the code
177*bcf317f8SAlex Bennéewhich has to work with either vhost or vhost-user uses
178*bcf317f8SAlex Bennée``vhost_dev_init()`` to instantiate the appropriate backend. This
179*bcf317f8SAlex Bennéemeans including a ``struct vhost_dev`` in the main object structure.
180*bcf317f8SAlex Bennée
181*bcf317f8SAlex BennéeFor vhost-user devices you also need to add code to track the
182*bcf317f8SAlex Bennéeinitialisation of the ``chardev`` device used for the control socket
183*bcf317f8SAlex Bennéebetween QEMU and the external vhost-user process.
184*bcf317f8SAlex Bennée
185*bcf317f8SAlex BennéeIf you only need to implement a vhost-user backed the other option is
186*bcf317f8SAlex Bennéea use a QOM-ified version of vhost-user.
187*bcf317f8SAlex Bennée
188*bcf317f8SAlex Bennée.. code:: c
189*bcf317f8SAlex Bennée
190*bcf317f8SAlex Bennée  static void
191*bcf317f8SAlex Bennée  vhost_user_gpu_instance_init(Object *obj)
192*bcf317f8SAlex Bennée  {
193*bcf317f8SAlex Bennée      VhostUserGPU *g = VHOST_USER_GPU(obj);
194*bcf317f8SAlex Bennée
195*bcf317f8SAlex Bennée      g->vhost = VHOST_USER_BACKEND(object_new(TYPE_VHOST_USER_BACKEND));
196*bcf317f8SAlex Bennée      object_property_add_alias(obj, "chardev",
197*bcf317f8SAlex Bennée                                OBJECT(g->vhost), "chardev");
198*bcf317f8SAlex Bennée  }
199*bcf317f8SAlex Bennée
200*bcf317f8SAlex Bennée  static const TypeInfo vhost_user_gpu_info = {
201*bcf317f8SAlex Bennée      .name = TYPE_VHOST_USER_GPU,
202*bcf317f8SAlex Bennée      .parent = TYPE_VIRTIO_GPU_BASE,
203*bcf317f8SAlex Bennée      .instance_size = sizeof(VhostUserGPU),
204*bcf317f8SAlex Bennée      .instance_init = vhost_user_gpu_instance_init,
205*bcf317f8SAlex Bennée      .instance_finalize = vhost_user_gpu_instance_finalize,
206*bcf317f8SAlex Bennée      .class_init = vhost_user_gpu_class_init,
207*bcf317f8SAlex Bennée  };
208*bcf317f8SAlex Bennée
209*bcf317f8SAlex BennéeUsing it this way entails adding a ``struct VhostUserBackend`` to your
210*bcf317f8SAlex Bennéecore object structure and manually instantiating the backend. This
211*bcf317f8SAlex Bennéesub-structure tracks both the ``vhost_dev`` and ``CharDev`` types
212*bcf317f8SAlex Bennéeneeded for the connection. Instead of calling ``vhost_dev_init`` you
213*bcf317f8SAlex Bennéewould call ``vhost_user_backend_dev_init`` which does what is needed
214*bcf317f8SAlex Bennéeon your behalf.
215