aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.d/buildtest.yml1
-rw-r--r--MAINTAINERS4
-rw-r--r--configs/targets/i386-softmmu.mak1
-rw-r--r--configs/targets/x86_64-softmmu.mak1
-rw-r--r--docs/about/deprecated.rst10
-rw-r--r--hw/display/virtio-gpu-udmabuf.c2
-rw-r--r--hw/i386/meson.build2
-rw-r--r--hw/i386/microvm-dt.c341
-rw-r--r--hw/i386/microvm-dt.h8
-rw-r--r--hw/i386/microvm.c2
-rw-r--r--hw/misc/sga.c2
-rw-r--r--include/hw/i386/microvm.h4
-rw-r--r--include/hw/usb/msd.h2
-rw-r--r--include/ui/console.h1
-rw-r--r--ui/console.c109
-rw-r--r--ui/gtk-egl.c40
-rw-r--r--ui/gtk-gl-area.c52
17 files changed, 466 insertions, 116 deletions
diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
index 5c378e3..6c1301e 100644
--- a/.gitlab-ci.d/buildtest.yml
+++ b/.gitlab-ci.d/buildtest.yml
@@ -575,7 +575,6 @@ build-without-default-features:
CONFIGURE_ARGS:
--without-default-features
--disable-capstone
- --disable-fdt
--disable-pie
--disable-qom-cast-debug
--disable-slirp
diff --git a/MAINTAINERS b/MAINTAINERS
index d58885d..7cbae14 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2302,11 +2302,13 @@ F: qapi/audio.json
ALSA Audio backend
M: Gerd Hoffmann <kraxel@redhat.com>
+R: Christian Schoenebeck <qemu_oss@crudebyte.com>
S: Odd Fixes
F: audio/alsaaudio.c
Core Audio framework backend
M: Gerd Hoffmann <kraxel@redhat.com>
+R: Christian Schoenebeck <qemu_oss@crudebyte.com>
S: Odd Fixes
F: audio/coreaudio.c
@@ -2317,6 +2319,7 @@ F: audio/dsound*
JACK Audio Connection Kit backend
M: Gerd Hoffmann <kraxel@redhat.com>
+R: Christian Schoenebeck <qemu_oss@crudebyte.com>
S: Odd Fixes
F: audio/jackaudio.c
@@ -2332,6 +2335,7 @@ F: audio/paaudio.c
SDL Audio backend
M: Gerd Hoffmann <kraxel@redhat.com>
+R: Thomas Huth <huth@tuxfamily.org>
S: Odd Fixes
F: audio/sdlaudio.c
diff --git a/configs/targets/i386-softmmu.mak b/configs/targets/i386-softmmu.mak
index 5babf71..6b3c99f 100644
--- a/configs/targets/i386-softmmu.mak
+++ b/configs/targets/i386-softmmu.mak
@@ -1,3 +1,4 @@
TARGET_ARCH=i386
TARGET_SUPPORTS_MTTCG=y
+TARGET_NEED_FDT=y
TARGET_XML_FILES= gdb-xml/i386-32bit.xml
diff --git a/configs/targets/x86_64-softmmu.mak b/configs/targets/x86_64-softmmu.mak
index 75e42bc..197817c 100644
--- a/configs/targets/x86_64-softmmu.mak
+++ b/configs/targets/x86_64-softmmu.mak
@@ -1,4 +1,5 @@
TARGET_ARCH=x86_64
TARGET_BASE_ARCH=i386
TARGET_SUPPORTS_MTTCG=y
+TARGET_NEED_FDT=y
TARGET_XML_FILES= gdb-xml/i386-64bit.xml
diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index be19317..25b7ec8 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -313,6 +313,16 @@ full SCSI support. Use virtio-scsi instead when SCSI passthrough is required.
Note this also applies to ``-device virtio-blk-pci,scsi=on|off``, which is an
alias.
+``-device sga`` (since 6.2)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The ``sga`` device loads an option ROM for x86 targets which enables
+SeaBIOS to send messages to the serial console. SeaBIOS 1.11.0 onwards
+contains native support for this feature and thus use of the option
+ROM approach is obsolete. The native SeaBIOS support can be activated
+by using ``-machine graphics=off``.
+
+
Block device options
''''''''''''''''''''
diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c
index c6f7f58..60ea7f8 100644
--- a/hw/display/virtio-gpu-udmabuf.c
+++ b/hw/display/virtio-gpu-udmabuf.c
@@ -186,7 +186,7 @@ static VGPUDMABuf
dmabuf->buf.fourcc = qemu_pixman_to_drm_format(fb->format);
dmabuf->buf.fd = res->dmabuf_fd;
dmabuf->buf.allow_fences = true;
-
+ dmabuf->buf.draw_submitted = false;
dmabuf->scanout_id = scanout_id;
QTAILQ_INSERT_HEAD(&g->dmabuf.bufs, dmabuf, next);
diff --git a/hw/i386/meson.build b/hw/i386/meson.build
index c502965..213e2e8 100644
--- a/hw/i386/meson.build
+++ b/hw/i386/meson.build
@@ -11,7 +11,7 @@ i386_ss.add(when: 'CONFIG_X86_IOMMU', if_true: files('x86-iommu.c'),
if_false: files('x86-iommu-stub.c'))
i386_ss.add(when: 'CONFIG_AMD_IOMMU', if_true: files('amd_iommu.c'))
i386_ss.add(when: 'CONFIG_I440FX', if_true: files('pc_piix.c'))
-i386_ss.add(when: 'CONFIG_MICROVM', if_true: files('microvm.c', 'acpi-microvm.c'))
+i386_ss.add(when: 'CONFIG_MICROVM', if_true: files('microvm.c', 'acpi-microvm.c', 'microvm-dt.c'))
i386_ss.add(when: 'CONFIG_Q35', if_true: files('pc_q35.c'))
i386_ss.add(when: 'CONFIG_VMMOUSE', if_true: files('vmmouse.c'))
i386_ss.add(when: 'CONFIG_VMPORT', if_true: files('vmport.c'))
diff --git a/hw/i386/microvm-dt.c b/hw/i386/microvm-dt.c
new file mode 100644
index 0000000..875ba91
--- /dev/null
+++ b/hw/i386/microvm-dt.c
@@ -0,0 +1,341 @@
+/*
+ * microvm device tree support
+ *
+ * This generates an device tree for microvm and exports it via fw_cfg
+ * as "etc/fdt" to the firmware (edk2 specifically).
+ *
+ * The use case is to allow edk2 find the pcie ecam and the virtio
+ * devices, without adding an ACPI parser, reusing the fdt parser
+ * which is needed anyway for the arm platform.
+ *
+ * Note 1: The device tree is incomplete. CPUs and memory is missing
+ * for example, those can be detected using other fw_cfg files.
+ * Also pci ecam irq routing is not there, edk2 doesn't use
+ * interrupts.
+ *
+ * Note 2: This is for firmware only. OSes should use the more
+ * complete ACPI tables for hardware discovery.
+ *
+ * ----------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "qemu/osdep.h"
+#include "qemu/cutils.h"
+#include "sysemu/device_tree.h"
+#include "hw/char/serial.h"
+#include "hw/i386/fw_cfg.h"
+#include "hw/rtc/mc146818rtc.h"
+#include "hw/sysbus.h"
+#include "hw/virtio/virtio-mmio.h"
+#include "hw/usb/xhci.h"
+
+#include "microvm-dt.h"
+
+static bool debug;
+
+static void dt_add_microvm_irq(MicrovmMachineState *mms,
+ const char *nodename, uint32_t irq)
+{
+ int index = 0;
+
+ if (irq >= IO_APIC_SECONDARY_IRQBASE) {
+ irq -= IO_APIC_SECONDARY_IRQBASE;
+ index++;
+ }
+
+ qemu_fdt_setprop_cell(mms->fdt, nodename, "interrupt-parent",
+ mms->ioapic_phandle[index]);
+ qemu_fdt_setprop_cells(mms->fdt, nodename, "interrupts", irq, 0);
+}
+
+static void dt_add_virtio(MicrovmMachineState *mms, VirtIOMMIOProxy *mmio)
+{
+ SysBusDevice *dev = SYS_BUS_DEVICE(mmio);
+ VirtioBusState *mmio_virtio_bus = &mmio->bus;
+ BusState *mmio_bus = &mmio_virtio_bus->parent_obj;
+ char *nodename;
+
+ if (QTAILQ_EMPTY(&mmio_bus->children)) {
+ return;
+ }
+
+ hwaddr base = dev->mmio[0].addr;
+ hwaddr size = 512;
+ unsigned index = (base - VIRTIO_MMIO_BASE) / size;
+ uint32_t irq = mms->virtio_irq_base + index;
+
+ nodename = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
+ qemu_fdt_add_subnode(mms->fdt, nodename);
+ qemu_fdt_setprop_string(mms->fdt, nodename, "compatible", "virtio,mmio");
+ qemu_fdt_setprop_sized_cells(mms->fdt, nodename, "reg", 2, base, 2, size);
+ qemu_fdt_setprop(mms->fdt, nodename, "dma-coherent", NULL, 0);
+ dt_add_microvm_irq(mms, nodename, irq);
+ g_free(nodename);
+}
+
+static void dt_add_xhci(MicrovmMachineState *mms)
+{
+ const char compat[] = "generic-xhci";
+ uint32_t irq = MICROVM_XHCI_IRQ;
+ hwaddr base = MICROVM_XHCI_BASE;
+ hwaddr size = XHCI_LEN_REGS;
+ char *nodename;
+
+ nodename = g_strdup_printf("/usb@%" PRIx64, base);
+ qemu_fdt_add_subnode(mms->fdt, nodename);
+ qemu_fdt_setprop(mms->fdt, nodename, "compatible", compat, sizeof(compat));
+ qemu_fdt_setprop_sized_cells(mms->fdt, nodename, "reg", 2, base, 2, size);
+ qemu_fdt_setprop(mms->fdt, nodename, "dma-coherent", NULL, 0);
+ dt_add_microvm_irq(mms, nodename, irq);
+ g_free(nodename);
+}
+
+static void dt_add_pcie(MicrovmMachineState *mms)
+{
+ hwaddr base = PCIE_MMIO_BASE;
+ int nr_pcie_buses;
+ char *nodename;
+
+ nodename = g_strdup_printf("/pcie@%" PRIx64, base);
+ qemu_fdt_add_subnode(mms->fdt, nodename);
+ qemu_fdt_setprop_string(mms->fdt, nodename,
+ "compatible", "pci-host-ecam-generic");
+ qemu_fdt_setprop_string(mms->fdt, nodename, "device_type", "pci");
+ qemu_fdt_setprop_cell(mms->fdt, nodename, "#address-cells", 3);
+ qemu_fdt_setprop_cell(mms->fdt, nodename, "#size-cells", 2);
+ qemu_fdt_setprop_cell(mms->fdt, nodename, "linux,pci-domain", 0);
+ qemu_fdt_setprop(mms->fdt, nodename, "dma-coherent", NULL, 0);
+
+ qemu_fdt_setprop_sized_cells(mms->fdt, nodename, "reg",
+ 2, PCIE_ECAM_BASE, 2, PCIE_ECAM_SIZE);
+ if (mms->gpex.mmio64.size) {
+ qemu_fdt_setprop_sized_cells(mms->fdt, nodename, "ranges",
+
+ 1, FDT_PCI_RANGE_MMIO,
+ 2, mms->gpex.mmio32.base,
+ 2, mms->gpex.mmio32.base,
+ 2, mms->gpex.mmio32.size,
+
+ 1, FDT_PCI_RANGE_MMIO_64BIT,
+ 2, mms->gpex.mmio64.base,
+ 2, mms->gpex.mmio64.base,
+ 2, mms->gpex.mmio64.size);
+ } else {
+ qemu_fdt_setprop_sized_cells(mms->fdt, nodename, "ranges",
+
+ 1, FDT_PCI_RANGE_MMIO,
+ 2, mms->gpex.mmio32.base,
+ 2, mms->gpex.mmio32.base,
+ 2, mms->gpex.mmio32.size);
+ }
+
+ nr_pcie_buses = PCIE_ECAM_SIZE / PCIE_MMCFG_SIZE_MIN;
+ qemu_fdt_setprop_cells(mms->fdt, nodename, "bus-range", 0,
+ nr_pcie_buses - 1);
+}
+
+static void dt_add_ioapic(MicrovmMachineState *mms, SysBusDevice *dev)
+{
+ hwaddr base = dev->mmio[0].addr;
+ char *nodename;
+ uint32_t ph;
+ int index;
+
+ switch (base) {
+ case IO_APIC_DEFAULT_ADDRESS:
+ index = 0;
+ break;
+ case IO_APIC_SECONDARY_ADDRESS:
+ index = 1;
+ break;
+ default:
+ fprintf(stderr, "unknown ioapic @ %" PRIx64 "\n", base);
+ return;
+ }
+
+ nodename = g_strdup_printf("/ioapic%d@%" PRIx64, index + 1, base);
+ qemu_fdt_add_subnode(mms->fdt, nodename);
+ qemu_fdt_setprop_string(mms->fdt, nodename,
+ "compatible", "intel,ce4100-ioapic");
+ qemu_fdt_setprop(mms->fdt, nodename, "interrupt-controller", NULL, 0);
+ qemu_fdt_setprop_cell(mms->fdt, nodename, "#interrupt-cells", 0x2);
+ qemu_fdt_setprop_cell(mms->fdt, nodename, "#address-cells", 0x2);
+ qemu_fdt_setprop_sized_cells(mms->fdt, nodename, "reg",
+ 2, base, 2, 0x1000);
+
+ ph = qemu_fdt_alloc_phandle(mms->fdt);
+ qemu_fdt_setprop_cell(mms->fdt, nodename, "phandle", ph);
+ qemu_fdt_setprop_cell(mms->fdt, nodename, "linux,phandle", ph);
+ mms->ioapic_phandle[index] = ph;
+
+ g_free(nodename);
+}
+
+static void dt_add_isa_serial(MicrovmMachineState *mms, ISADevice *dev)
+{
+ const char compat[] = "ns16550";
+ uint32_t irq = object_property_get_int(OBJECT(dev), "irq", NULL);
+ hwaddr base = object_property_get_int(OBJECT(dev), "iobase", NULL);
+ hwaddr size = 8;
+ char *nodename;
+
+ nodename = g_strdup_printf("/serial@%" PRIx64, base);
+ qemu_fdt_add_subnode(mms->fdt, nodename);
+ qemu_fdt_setprop(mms->fdt, nodename, "compatible", compat, sizeof(compat));
+ qemu_fdt_setprop_sized_cells(mms->fdt, nodename, "reg", 2, base, 2, size);
+ dt_add_microvm_irq(mms, nodename, irq);
+
+ if (base == 0x3f8 /* com1 */) {
+ qemu_fdt_setprop_string(mms->fdt, "/chosen", "stdout-path", nodename);
+ }
+
+ g_free(nodename);
+}
+
+static void dt_add_isa_rtc(MicrovmMachineState *mms, ISADevice *dev)
+{
+ const char compat[] = "motorola,mc146818";
+ uint32_t irq = RTC_ISA_IRQ;
+ hwaddr base = RTC_ISA_BASE;
+ hwaddr size = 8;
+ char *nodename;
+
+ nodename = g_strdup_printf("/rtc@%" PRIx64, base);
+ qemu_fdt_add_subnode(mms->fdt, nodename);
+ qemu_fdt_setprop(mms->fdt, nodename, "compatible", compat, sizeof(compat));
+ qemu_fdt_setprop_sized_cells(mms->fdt, nodename, "reg", 2, base, 2, size);
+ dt_add_microvm_irq(mms, nodename, irq);
+ g_free(nodename);
+}
+
+static void dt_setup_isa_bus(MicrovmMachineState *mms, DeviceState *bridge)
+{
+ BusState *bus = qdev_get_child_bus(bridge, "isa.0");
+ BusChild *kid;
+ Object *obj;
+
+ QTAILQ_FOREACH(kid, &bus->children, sibling) {
+ DeviceState *dev = kid->child;
+
+ /* serial */
+ obj = object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL);
+ if (obj) {
+ dt_add_isa_serial(mms, ISA_DEVICE(obj));
+ continue;
+ }
+
+ /* rtc */
+ obj = object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC);
+ if (obj) {
+ dt_add_isa_rtc(mms, ISA_DEVICE(obj));
+ continue;
+ }
+
+ if (debug) {
+ fprintf(stderr, "%s: unhandled: %s\n", __func__,
+ object_get_typename(OBJECT(dev)));
+ }
+ }
+}
+
+static void dt_setup_sys_bus(MicrovmMachineState *mms)
+{
+ BusState *bus;
+ BusChild *kid;
+ Object *obj;
+
+ /* sysbus devices */
+ bus = sysbus_get_default();
+ QTAILQ_FOREACH(kid, &bus->children, sibling) {
+ DeviceState *dev = kid->child;
+
+ /* ioapic */
+ obj = object_dynamic_cast(OBJECT(dev), TYPE_IOAPIC);
+ if (obj) {
+ dt_add_ioapic(mms, SYS_BUS_DEVICE(obj));
+ continue;
+ }
+ }
+
+ QTAILQ_FOREACH(kid, &bus->children, sibling) {
+ DeviceState *dev = kid->child;
+
+ /* virtio */
+ obj = object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MMIO);
+ if (obj) {
+ dt_add_virtio(mms, VIRTIO_MMIO(obj));
+ continue;
+ }
+
+ /* xhci */
+ obj = object_dynamic_cast(OBJECT(dev), TYPE_XHCI_SYSBUS);
+ if (obj) {
+ dt_add_xhci(mms);
+ continue;
+ }
+
+ /* pcie */
+ obj = object_dynamic_cast(OBJECT(dev), TYPE_GPEX_HOST);
+ if (obj) {
+ dt_add_pcie(mms);
+ continue;
+ }
+
+ /* isa */
+ obj = object_dynamic_cast(OBJECT(dev), "isabus-bridge");
+ if (obj) {
+ dt_setup_isa_bus(mms, DEVICE(obj));
+ continue;
+ }
+
+ if (debug) {
+ obj = object_dynamic_cast(OBJECT(dev), TYPE_IOAPIC);
+ if (obj) {
+ /* ioapic already added in first pass */
+ continue;
+ }
+ fprintf(stderr, "%s: unhandled: %s\n", __func__,
+ object_get_typename(OBJECT(dev)));
+ }
+ }
+}
+
+void dt_setup_microvm(MicrovmMachineState *mms)
+{
+ X86MachineState *x86ms = X86_MACHINE(mms);
+ int size = 0;
+
+ mms->fdt = create_device_tree(&size);
+
+ /* root node */
+ qemu_fdt_setprop_string(mms->fdt, "/", "compatible", "linux,microvm");
+ qemu_fdt_setprop_cell(mms->fdt, "/", "#address-cells", 0x2);
+ qemu_fdt_setprop_cell(mms->fdt, "/", "#size-cells", 0x2);
+
+ qemu_fdt_add_subnode(mms->fdt, "/chosen");
+ dt_setup_sys_bus(mms);
+
+ /* add to fw_cfg */
+ fprintf(stderr, "%s: add etc/fdt to fw_cfg\n", __func__);
+ fw_cfg_add_file(x86ms->fw_cfg, "etc/fdt", mms->fdt, size);
+
+ if (debug) {
+ fprintf(stderr, "%s: writing microvm.fdt\n", __func__);
+ g_file_set_contents("microvm.fdt", mms->fdt, size, NULL);
+ int ret = system("dtc -I dtb -O dts microvm.fdt");
+ if (ret != 0) {
+ fprintf(stderr, "%s: oops, dtc not installed?\n", __func__);
+ }
+ }
+}
diff --git a/hw/i386/microvm-dt.h b/hw/i386/microvm-dt.h
new file mode 100644
index 0000000..77c79cb
--- /dev/null
+++ b/hw/i386/microvm-dt.h
@@ -0,0 +1,8 @@
+#ifndef HW_I386_MICROVM_DT_H
+#define HW_I386_MICROVM_DT_H
+
+#include "hw/i386/microvm.h"
+
+void dt_setup_microvm(MicrovmMachineState *mms);
+
+#endif
diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
index f257ec5..8d6ebea 100644
--- a/hw/i386/microvm.c
+++ b/hw/i386/microvm.c
@@ -28,6 +28,7 @@
#include "sysemu/reset.h"
#include "sysemu/runstate.h"
#include "acpi-microvm.h"
+#include "microvm-dt.h"
#include "hw/loader.h"
#include "hw/irq.h"
@@ -626,6 +627,7 @@ static void microvm_machine_done(Notifier *notifier, void *data)
machine_done);
acpi_setup_microvm(mms);
+ dt_setup_microvm(mms);
}
static void microvm_powerdown_req(Notifier *notifier, void *data)
diff --git a/hw/misc/sga.c b/hw/misc/sga.c
index 4dbe6d7..1d04672 100644
--- a/hw/misc/sga.c
+++ b/hw/misc/sga.c
@@ -30,6 +30,7 @@
#include "hw/loader.h"
#include "qemu/module.h"
#include "qom/object.h"
+#include "qemu/error-report.h"
#define SGABIOS_FILENAME "sgabios.bin"
@@ -42,6 +43,7 @@ struct ISASGAState {
static void sga_realizefn(DeviceState *dev, Error **errp)
{
+ warn_report("-device sga is deprecated, use -machine graphics=off");
rom_add_vga(SGABIOS_FILENAME);
}
diff --git a/include/hw/i386/microvm.h b/include/hw/i386/microvm.h
index f25f837..4d9c732 100644
--- a/include/hw/i386/microvm.h
+++ b/include/hw/i386/microvm.h
@@ -104,6 +104,10 @@ struct MicrovmMachineState {
Notifier machine_done;
Notifier powerdown_req;
struct GPEXConfig gpex;
+
+ /* device tree */
+ void *fdt;
+ uint32_t ioapic_phandle[2];
};
#define TYPE_MICROVM_MACHINE MACHINE_TYPE_NAME("microvm")
diff --git a/include/hw/usb/msd.h b/include/hw/usb/msd.h
index 7538c54..54e9f38 100644
--- a/include/hw/usb/msd.h
+++ b/include/hw/usb/msd.h
@@ -17,7 +17,7 @@ enum USBMSDMode {
USB_MSDM_CSW /* Command Status. */
};
-struct usb_msd_csw {
+struct QEMU_PACKED usb_msd_csw {
uint32_t sig;
uint32_t tag;
uint32_t residue;
diff --git a/include/ui/console.h b/include/ui/console.h
index 244664d..b6bedc5 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -171,6 +171,7 @@ typedef struct QemuDmaBuf {
void *sync;
int fence_fd;
bool allow_fences;
+ bool draw_submitted;
} QemuDmaBuf;
typedef struct DisplayState DisplayState;
diff --git a/ui/console.c b/ui/console.c
index eabbbc9..29a3e3f 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -27,10 +27,12 @@
#include "hw/qdev-core.h"
#include "qapi/error.h"
#include "qapi/qapi-commands-ui.h"
+#include "qemu/fifo8.h"
+#include "qemu/main-loop.h"
#include "qemu/module.h"
#include "qemu/option.h"
#include "qemu/timer.h"
-#include "chardev/char-fe.h"
+#include "chardev/char.h"
#include "trace.h"
#include "exec/memory.h"
#include "io/channel-file.h"
@@ -62,57 +64,6 @@ enum TTYState {
TTY_STATE_CSI,
};
-typedef struct QEMUFIFO {
- uint8_t *buf;
- int buf_size;
- int count, wptr, rptr;
-} QEMUFIFO;
-
-static int qemu_fifo_write(QEMUFIFO *f, const uint8_t *buf, int len1)
-{
- int l, len;
-
- l = f->buf_size - f->count;
- if (len1 > l)
- len1 = l;
- len = len1;
- while (len > 0) {
- l = f->buf_size - f->wptr;
- if (l > len)
- l = len;
- memcpy(f->buf + f->wptr, buf, l);
- f->wptr += l;
- if (f->wptr >= f->buf_size)
- f->wptr = 0;
- buf += l;
- len -= l;
- }
- f->count += len1;
- return len1;
-}
-
-static int qemu_fifo_read(QEMUFIFO *f, uint8_t *buf, int len1)
-{
- int l, len;
-
- if (len1 > f->count)
- len1 = f->count;
- len = len1;
- while (len > 0) {
- l = f->buf_size - f->rptr;
- if (l > len)
- l = len;
- memcpy(buf, f->buf + f->rptr, l);
- f->rptr += l;
- if (f->rptr >= f->buf_size)
- f->rptr = 0;
- buf += l;
- len -= l;
- }
- f->count -= len1;
- return len1;
-}
-
typedef enum {
GRAPHIC_CONSOLE,
TEXT_CONSOLE,
@@ -165,9 +116,7 @@ struct QemuConsole {
Chardev *chr;
/* fifo for key pressed */
- QEMUFIFO out_fifo;
- uint8_t out_fifo_buf[16];
- QEMUTimer *kbd_timer;
+ Fifo8 out_fifo;
CoQueue dump_queue;
QTAILQ_ENTRY(QemuConsole) next;
@@ -1157,25 +1106,20 @@ static int vc_chr_write(Chardev *chr, const uint8_t *buf, int len)
return len;
}
-static void kbd_send_chars(void *opaque)
+static void kbd_send_chars(QemuConsole *s)
{
- QemuConsole *s = opaque;
- int len;
- uint8_t buf[16];
+ uint32_t len, avail;
len = qemu_chr_be_can_write(s->chr);
- if (len > s->out_fifo.count)
- len = s->out_fifo.count;
- if (len > 0) {
- if (len > sizeof(buf))
- len = sizeof(buf);
- qemu_fifo_read(&s->out_fifo, buf, len);
- qemu_chr_be_write(s->chr, buf, len);
- }
- /* characters are pending: we send them a bit later (XXX:
- horrible, should change char device API) */
- if (s->out_fifo.count > 0) {
- timer_mod(s->kbd_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1);
+ avail = fifo8_num_used(&s->out_fifo);
+ while (len > 0 && avail > 0) {
+ const uint8_t *buf;
+ uint32_t size;
+
+ buf = fifo8_pop_buf(&s->out_fifo, MIN(len, avail), &size);
+ qemu_chr_be_write(s->chr, (uint8_t *)buf, size);
+ len = qemu_chr_be_can_write(s->chr);
+ avail -= size;
}
}
@@ -1183,8 +1127,8 @@ static void kbd_send_chars(void *opaque)
void kbd_put_keysym_console(QemuConsole *s, int keysym)
{
uint8_t buf[16], *q;
- CharBackend *be;
int c;
+ uint32_t num_free;
if (!s || (s->console_type == GRAPHIC_CONSOLE))
return;
@@ -1226,11 +1170,9 @@ void kbd_put_keysym_console(QemuConsole *s, int keysym)
if (s->echo) {
vc_chr_write(s->chr, buf, q - buf);
}
- be = s->chr->be;
- if (be && be->chr_read) {
- qemu_fifo_write(&s->out_fifo, buf, q - buf);
- kbd_send_chars(s);
- }
+ num_free = fifo8_num_free(&s->out_fifo);
+ fifo8_push_all(&s->out_fifo, buf, MIN(num_free, q - buf));
+ kbd_send_chars(s);
break;
}
}
@@ -2186,6 +2128,14 @@ int qemu_console_get_height(QemuConsole *con, int fallback)
return con ? surface_height(con->surface) : fallback;
}
+static void vc_chr_accept_input(Chardev *chr)
+{
+ VCChardev *drv = VC_CHARDEV(chr);
+ QemuConsole *s = drv->console;
+
+ kbd_send_chars(s);
+}
+
static void vc_chr_set_echo(Chardev *chr, bool echo)
{
VCChardev *drv = VC_CHARDEV(chr);
@@ -2233,9 +2183,7 @@ static void text_console_do_init(Chardev *chr, DisplayState *ds)
int g_width = 80 * FONT_WIDTH;
int g_height = 24 * FONT_HEIGHT;
- s->out_fifo.buf = s->out_fifo_buf;
- s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
- s->kbd_timer = timer_new_ms(QEMU_CLOCK_REALTIME, kbd_send_chars, s);
+ fifo8_create(&s->out_fifo, 16);
s->ds = ds;
s->y_displayed = 0;
@@ -2485,6 +2433,7 @@ static void char_vc_class_init(ObjectClass *oc, void *data)
cc->parse = qemu_chr_parse_vc;
cc->open = vc_chr_open;
cc->chr_write = vc_chr_write;
+ cc->chr_accept_input = vc_chr_accept_input;
cc->chr_set_echo = vc_chr_set_echo;
}
diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
index 72ce5e1..e912b20 100644
--- a/ui/gtk-egl.c
+++ b/ui/gtk-egl.c
@@ -63,6 +63,9 @@ void gd_egl_init(VirtualConsole *vc)
void gd_egl_draw(VirtualConsole *vc)
{
GdkWindow *window;
+#ifdef CONFIG_GBM
+ QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
+#endif
int ww, wh;
if (!vc->gfx.gls) {
@@ -74,10 +77,31 @@ void gd_egl_draw(VirtualConsole *vc)
wh = gdk_window_get_height(window);
if (vc->gfx.scanout_mode) {
+#ifdef CONFIG_GBM
+ if (dmabuf) {
+ if (!dmabuf->draw_submitted) {
+ return;
+ } else {
+ dmabuf->draw_submitted = false;
+ }
+ }
+#endif
gd_egl_scanout_flush(&vc->gfx.dcl, 0, 0, vc->gfx.w, vc->gfx.h);
vc->gfx.scale_x = (double)ww / vc->gfx.w;
vc->gfx.scale_y = (double)wh / vc->gfx.h;
+
+ glFlush();
+#ifdef CONFIG_GBM
+ if (dmabuf) {
+ egl_dmabuf_create_fence(dmabuf);
+ if (dmabuf->fence_fd > 0) {
+ qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc);
+ return;
+ }
+ graphic_hw_gl_block(vc->gfx.dcl.con, false);
+ }
+#endif
} else {
if (!vc->gfx.ds) {
return;
@@ -92,21 +116,10 @@ void gd_egl_draw(VirtualConsole *vc)
vc->gfx.scale_x = (double)ww / surface_width(vc->gfx.ds);
vc->gfx.scale_y = (double)wh / surface_height(vc->gfx.ds);
- }
-
- glFlush();
-#ifdef CONFIG_GBM
- if (vc->gfx.guest_fb.dmabuf) {
- QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
- egl_dmabuf_create_fence(dmabuf);
- if (dmabuf->fence_fd > 0) {
- qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc);
- return;
- }
- graphic_hw_gl_block(vc->gfx.dcl.con, false);
+ glFlush();
}
-#endif
+
graphic_hw_gl_flushed(vc->gfx.dcl.con);
}
@@ -317,6 +330,7 @@ void gd_egl_flush(DisplayChangeListener *dcl,
if (vc->gfx.guest_fb.dmabuf) {
graphic_hw_gl_block(vc->gfx.dcl.con, true);
+ vc->gfx.guest_fb.dmabuf->draw_submitted = true;
gtk_widget_queue_draw_area(area, x, y, w, h);
return;
}
diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
index b235237..461da77 100644
--- a/ui/gtk-gl-area.c
+++ b/ui/gtk-gl-area.c
@@ -38,6 +38,9 @@ static void gtk_gl_area_set_scanout_mode(VirtualConsole *vc, bool scanout)
void gd_gl_area_draw(VirtualConsole *vc)
{
+#ifdef CONFIG_GBM
+ QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
+#endif
int ww, wh, y1, y2;
if (!vc->gfx.gls) {
@@ -53,6 +56,16 @@ void gd_gl_area_draw(VirtualConsole *vc)
return;
}
+#ifdef CONFIG_GBM
+ if (dmabuf) {
+ if (!dmabuf->draw_submitted) {
+ return;
+ } else {
+ dmabuf->draw_submitted = false;
+ }
+ }
+#endif
+
glBindFramebuffer(GL_READ_FRAMEBUFFER, vc->gfx.guest_fb.framebuffer);
/* GtkGLArea sets GL_DRAW_FRAMEBUFFER for us */
@@ -62,6 +75,22 @@ void gd_gl_area_draw(VirtualConsole *vc)
glBlitFramebuffer(0, y1, vc->gfx.w, y2,
0, 0, ww, wh,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
+#ifdef CONFIG_GBM
+ if (dmabuf) {
+ egl_dmabuf_create_sync(dmabuf);
+ }
+#endif
+ glFlush();
+#ifdef CONFIG_GBM
+ if (dmabuf) {
+ egl_dmabuf_create_fence(dmabuf);
+ if (dmabuf->fence_fd > 0) {
+ qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc);
+ return;
+ }
+ graphic_hw_gl_block(vc->gfx.dcl.con, false);
+ }
+#endif
} else {
if (!vc->gfx.ds) {
return;
@@ -72,25 +101,6 @@ void gd_gl_area_draw(VirtualConsole *vc)
surface_gl_render_texture(vc->gfx.gls, vc->gfx.ds);
}
-#ifdef CONFIG_GBM
- if (vc->gfx.guest_fb.dmabuf) {
- egl_dmabuf_create_sync(vc->gfx.guest_fb.dmabuf);
- }
-#endif
-
- glFlush();
-#ifdef CONFIG_GBM
- if (vc->gfx.guest_fb.dmabuf) {
- QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
-
- egl_dmabuf_create_fence(dmabuf);
- if (dmabuf->fence_fd > 0) {
- qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc);
- return;
- }
- graphic_hw_gl_block(vc->gfx.dcl.con, false);
- }
-#endif
graphic_hw_gl_flushed(vc->gfx.dcl.con);
}
@@ -112,6 +122,9 @@ void gd_gl_area_refresh(DisplayChangeListener *dcl)
{
VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
+ vc->gfx.dcl.update_interval = gd_monitor_update_interval(
+ vc->window ? vc->window : vc->gfx.drawing_area);
+
if (!vc->gfx.gls) {
if (!gtk_widget_get_realized(vc->gfx.drawing_area)) {
return;
@@ -234,6 +247,7 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl,
if (vc->gfx.guest_fb.dmabuf) {
graphic_hw_gl_block(vc->gfx.dcl.con, true);
+ vc->gfx.guest_fb.dmabuf->draw_submitted = true;
}
gtk_gl_area_queue_render(GTK_GL_AREA(vc->gfx.drawing_area));
}