2
0

virtio-vga.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. #include "qemu/osdep.h"
  2. #include "hw/pci/pci.h"
  3. #include "hw/qdev-properties.h"
  4. #include "hw/virtio/virtio-gpu.h"
  5. #include "qapi/error.h"
  6. #include "qemu/module.h"
  7. #include "virtio-vga.h"
  8. static void virtio_vga_base_invalidate_display(void *opaque)
  9. {
  10. VirtIOVGABase *vvga = opaque;
  11. VirtIOGPUBase *g = vvga->vgpu;
  12. if (g->enable) {
  13. virtio_gpu_ops.invalidate(g);
  14. } else {
  15. vvga->vga.hw_ops->invalidate(&vvga->vga);
  16. }
  17. }
  18. static void virtio_vga_base_update_display(void *opaque)
  19. {
  20. VirtIOVGABase *vvga = opaque;
  21. VirtIOGPUBase *g = vvga->vgpu;
  22. if (g->enable) {
  23. virtio_gpu_ops.gfx_update(g);
  24. } else {
  25. vvga->vga.hw_ops->gfx_update(&vvga->vga);
  26. }
  27. }
  28. static void virtio_vga_base_text_update(void *opaque, console_ch_t *chardata)
  29. {
  30. VirtIOVGABase *vvga = opaque;
  31. VirtIOGPUBase *g = vvga->vgpu;
  32. if (g->enable) {
  33. if (virtio_gpu_ops.text_update) {
  34. virtio_gpu_ops.text_update(g, chardata);
  35. }
  36. } else {
  37. if (vvga->vga.hw_ops->text_update) {
  38. vvga->vga.hw_ops->text_update(&vvga->vga, chardata);
  39. }
  40. }
  41. }
  42. static int virtio_vga_base_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
  43. {
  44. VirtIOVGABase *vvga = opaque;
  45. VirtIOGPUBase *g = vvga->vgpu;
  46. if (virtio_gpu_ops.ui_info) {
  47. return virtio_gpu_ops.ui_info(g, idx, info);
  48. }
  49. return -1;
  50. }
  51. static void virtio_vga_base_gl_block(void *opaque, bool block)
  52. {
  53. VirtIOVGABase *vvga = opaque;
  54. VirtIOGPUBase *g = vvga->vgpu;
  55. if (virtio_gpu_ops.gl_block) {
  56. virtio_gpu_ops.gl_block(g, block);
  57. }
  58. }
  59. static const GraphicHwOps virtio_vga_base_ops = {
  60. .invalidate = virtio_vga_base_invalidate_display,
  61. .gfx_update = virtio_vga_base_update_display,
  62. .text_update = virtio_vga_base_text_update,
  63. .ui_info = virtio_vga_base_ui_info,
  64. .gl_block = virtio_vga_base_gl_block,
  65. };
  66. static const VMStateDescription vmstate_virtio_vga_base = {
  67. .name = "virtio-vga",
  68. .version_id = 2,
  69. .minimum_version_id = 2,
  70. .fields = (VMStateField[]) {
  71. /* no pci stuff here, saving the virtio device will handle that */
  72. VMSTATE_STRUCT(vga, VirtIOVGABase, 0,
  73. vmstate_vga_common, VGACommonState),
  74. VMSTATE_END_OF_LIST()
  75. }
  76. };
  77. /* VGA device wrapper around PCI device around virtio GPU */
  78. static void virtio_vga_base_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
  79. {
  80. VirtIOVGABase *vvga = VIRTIO_VGA_BASE(vpci_dev);
  81. VirtIOGPUBase *g = vvga->vgpu;
  82. VGACommonState *vga = &vvga->vga;
  83. Error *err = NULL;
  84. uint32_t offset;
  85. int i;
  86. /* init vga compat bits */
  87. vga->vram_size_mb = 8;
  88. vga_common_init(vga, OBJECT(vpci_dev));
  89. vga_init(vga, OBJECT(vpci_dev), pci_address_space(&vpci_dev->pci_dev),
  90. pci_address_space_io(&vpci_dev->pci_dev), true);
  91. pci_register_bar(&vpci_dev->pci_dev, 0,
  92. PCI_BASE_ADDRESS_MEM_PREFETCH, &vga->vram);
  93. /*
  94. * Configure virtio bar and regions
  95. *
  96. * We use bar #2 for the mmio regions, to be compatible with stdvga.
  97. * virtio regions are moved to the end of bar #2, to make room for
  98. * the stdvga mmio registers at the start of bar #2.
  99. */
  100. vpci_dev->modern_mem_bar_idx = 2;
  101. vpci_dev->msix_bar_idx = 4;
  102. if (!(vpci_dev->flags & VIRTIO_PCI_FLAG_PAGE_PER_VQ)) {
  103. /*
  104. * with page-per-vq=off there is no padding space we can use
  105. * for the stdvga registers. Make the common and isr regions
  106. * smaller then.
  107. */
  108. vpci_dev->common.size /= 2;
  109. vpci_dev->isr.size /= 2;
  110. }
  111. offset = memory_region_size(&vpci_dev->modern_bar);
  112. offset -= vpci_dev->notify.size;
  113. vpci_dev->notify.offset = offset;
  114. offset -= vpci_dev->device.size;
  115. vpci_dev->device.offset = offset;
  116. offset -= vpci_dev->isr.size;
  117. vpci_dev->isr.offset = offset;
  118. offset -= vpci_dev->common.size;
  119. vpci_dev->common.offset = offset;
  120. /* init virtio bits */
  121. qdev_set_parent_bus(DEVICE(g), BUS(&vpci_dev->bus));
  122. virtio_pci_force_virtio_1(vpci_dev);
  123. object_property_set_bool(OBJECT(g), true, "realized", &err);
  124. if (err) {
  125. error_propagate(errp, err);
  126. return;
  127. }
  128. /* add stdvga mmio regions */
  129. pci_std_vga_mmio_region_init(vga, OBJECT(vvga), &vpci_dev->modern_bar,
  130. vvga->vga_mrs, true, false);
  131. vga->con = g->scanout[0].con;
  132. graphic_console_set_hwops(vga->con, &virtio_vga_base_ops, vvga);
  133. for (i = 0; i < g->conf.max_outputs; i++) {
  134. object_property_set_link(OBJECT(g->scanout[i].con),
  135. OBJECT(vpci_dev),
  136. "device", errp);
  137. }
  138. }
  139. static void virtio_vga_base_reset(DeviceState *dev)
  140. {
  141. VirtIOVGABaseClass *klass = VIRTIO_VGA_BASE_GET_CLASS(dev);
  142. VirtIOVGABase *vvga = VIRTIO_VGA_BASE(dev);
  143. /* reset virtio-gpu */
  144. klass->parent_reset(dev);
  145. /* reset vga */
  146. vga_common_reset(&vvga->vga);
  147. vga_dirty_log_start(&vvga->vga);
  148. }
  149. static Property virtio_vga_base_properties[] = {
  150. DEFINE_VIRTIO_GPU_PCI_PROPERTIES(VirtIOPCIProxy),
  151. DEFINE_PROP_END_OF_LIST(),
  152. };
  153. static void virtio_vga_base_class_init(ObjectClass *klass, void *data)
  154. {
  155. DeviceClass *dc = DEVICE_CLASS(klass);
  156. VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
  157. VirtIOVGABaseClass *v = VIRTIO_VGA_BASE_CLASS(klass);
  158. PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
  159. set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
  160. dc->props = virtio_vga_base_properties;
  161. dc->vmsd = &vmstate_virtio_vga_base;
  162. dc->hotpluggable = false;
  163. device_class_set_parent_reset(dc, virtio_vga_base_reset,
  164. &v->parent_reset);
  165. k->realize = virtio_vga_base_realize;
  166. pcidev_k->romfile = "vgabios-virtio.bin";
  167. pcidev_k->class_id = PCI_CLASS_DISPLAY_VGA;
  168. }
  169. static TypeInfo virtio_vga_base_info = {
  170. .name = TYPE_VIRTIO_VGA_BASE,
  171. .parent = TYPE_VIRTIO_PCI,
  172. .instance_size = sizeof(struct VirtIOVGABase),
  173. .class_size = sizeof(struct VirtIOVGABaseClass),
  174. .class_init = virtio_vga_base_class_init,
  175. .abstract = true,
  176. };
  177. #define TYPE_VIRTIO_VGA "virtio-vga"
  178. #define VIRTIO_VGA(obj) \
  179. OBJECT_CHECK(VirtIOVGA, (obj), TYPE_VIRTIO_VGA)
  180. typedef struct VirtIOVGA {
  181. VirtIOVGABase parent_obj;
  182. VirtIOGPU vdev;
  183. } VirtIOVGA;
  184. static void virtio_vga_inst_initfn(Object *obj)
  185. {
  186. VirtIOVGA *dev = VIRTIO_VGA(obj);
  187. virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
  188. TYPE_VIRTIO_GPU);
  189. VIRTIO_VGA_BASE(dev)->vgpu = VIRTIO_GPU_BASE(&dev->vdev);
  190. }
  191. static VirtioPCIDeviceTypeInfo virtio_vga_info = {
  192. .generic_name = TYPE_VIRTIO_VGA,
  193. .parent = TYPE_VIRTIO_VGA_BASE,
  194. .instance_size = sizeof(struct VirtIOVGA),
  195. .instance_init = virtio_vga_inst_initfn,
  196. };
  197. static void virtio_vga_register_types(void)
  198. {
  199. type_register_static(&virtio_vga_base_info);
  200. virtio_pci_types_register(&virtio_vga_info);
  201. }
  202. type_init(virtio_vga_register_types)