MAINTAINERS: audio updates

microvm: device tree support
 console: chardev fixes
 misc: deprecate sga
 usb: fix struct usb_msd_csw
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEoDKM/7k6F6eZAf59TLbY7tPocTgFAmGBZp8ACgkQTLbY7tPo
 cTg/fxAAj4z7EqdQXykN4ra+JWbmxp9KE4Y7uDb7XIuzG1KRU/7zZeVaZ2+0X1R9
 9LicHo4wd0DN3JfHrkrQrpEN22zB0x7zUh9/5F7jtdOUzKf8GuhxBq9EmFpS5Uk1
 w4a/5bEmbfOf9G9kGm6DWFvUGj9AzmeCoJFCGxzWTjcqNQlyk/P1Plsq7m21RIXy
 le2tCevivE6LzxGZLXBH3YO0wjI6oSHBGaN9/0lOj4bUMGls5NpRB9gFR8IFcFeo
 XTGeJeB+INVt3/kTft65HkPqLif9FU/8Q/cqiglauLUyLFRVwe1sGtL7gnwmYBat
 xELqemBp0eVId+X1EOjkx2jdd70pwTxLT0alG/e34PsWF020AJIYvgLkXYS0FUqV
 PZDILgz6bGJ7o+vy0uYDzS20wMjBYhZ5UCuew4rN9xRxWA1qdJ8pk+4Bmal77oxQ
 cn/7pSkhD/Yz6ya/7yFNzzhy44Id8WRlYTbtjrgSvISSW+UHFotT/+io3dzdRuzC
 DnXl+DusxiCbNm0uE6xufS1gQLMlWqy8eAYrforIziVJG+RpxRjU0bTtzqyTqjm4
 MPiBWTM5InbM7IhoRo+x00vREPO5nGmtKCruaYW39uxT7MXQvociFObnspuwdfsc
 ZWwsMH79DSjpx8lXYyyls5uyEIgjY6mPYL9r8m1b2T05EF6Vy9E=
 =cLSX
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/kraxel/tags/misc-20211102-pull-request' into staging

MAINTAINERS: audio updates
microvm: device tree support
console: chardev fixes
misc: deprecate sga
usb: fix struct usb_msd_csw

# gpg: Signature made Tue 02 Nov 2021 12:26:07 PM EDT
# gpg:                using RSA key A0328CFFB93A17A79901FE7D4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full]
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>" [full]
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full]

* remotes/kraxel/tags/misc-20211102-pull-request:
  usb-storage: tag usb_msd_csw as packed struct
  hw/misc: deprecate the 'sga' device
  ui/console: remove chardev frontend connected test
  ui/console: replace kbd_timer with chr_accept_input callback
  ui/console: replace QEMUFIFO with Fifo8
  ui/gtk: skip any extra draw of same guest scanout blob res
  ui/gtk: Update the refresh rate for gl-area too
  microvm: add device tree support.
  MAINTAINERS: add myself as partial audio reviewer
  MAINTAINERS: Add myself as a reviewer for SDL audio

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
master
Richard Henderson 2021-11-03 02:28:14 -04:00
commit 58b6476164
17 changed files with 466 additions and 116 deletions

View File

@ -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

View File

@ -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

View File

@ -1,3 +1,4 @@
TARGET_ARCH=i386
TARGET_SUPPORTS_MTTCG=y
TARGET_NEED_FDT=y
TARGET_XML_FILES= gdb-xml/i386-32bit.xml

View File

@ -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

View File

@ -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
''''''''''''''''''''

View File

@ -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);

View File

@ -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'))

341
hw/i386/microvm-dt.c Normal file
View File

@ -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__);
}
}
}

8
hw/i386/microvm-dt.h Normal file
View File

@ -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

View File

@ -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)

View File

@ -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);
}

View File

@ -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")

View File

@ -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;

View File

@ -171,6 +171,7 @@ typedef struct QemuDmaBuf {
void *sync;
int fence_fd;
bool allow_fences;
bool draw_submitted;
} QemuDmaBuf;
typedef struct DisplayState DisplayState;

View File

@ -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;
}

View File

@ -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();
}
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);
}
@ -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;
}

View File

@ -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));
}