From patchwork Fri Mar 23 12:25:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 889960 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4072rN30zSz9s0b for ; Fri, 23 Mar 2018 23:28:20 +1100 (AEDT) Received: from localhost ([::1]:37767 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ezLnt-0007co-S1 for incoming@patchwork.ozlabs.org; Fri, 23 Mar 2018 08:28:17 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33972) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ezLlK-0005p6-UB for qemu-devel@nongnu.org; Fri, 23 Mar 2018 08:25:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ezLlJ-0002Pc-Qg for qemu-devel@nongnu.org; Fri, 23 Mar 2018 08:25:38 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:60666 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ezLlJ-0002P0-Lu for qemu-devel@nongnu.org; Fri, 23 Mar 2018 08:25:37 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 581507D843 for ; Fri, 23 Mar 2018 12:25:26 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-39.ams2.redhat.com [10.36.116.39]) by smtp.corp.redhat.com (Postfix) with ESMTP id C40342023231; Fri, 23 Mar 2018 12:25:21 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 2A9B399AE7; Fri, 23 Mar 2018 13:25:21 +0100 (CET) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Fri, 23 Mar 2018 13:25:16 +0100 Message-Id: <20180323122520.11270-4-kraxel@redhat.com> In-Reply-To: <20180323122520.11270-1-kraxel@redhat.com> References: <20180323122520.11270-1-kraxel@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Fri, 23 Mar 2018 12:25:27 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Fri, 23 Mar 2018 12:25:27 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kraxel@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v2 3/7] hw/display: add ramfb, a simple boot framebuffer living in guest ram X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alex Williamson , =?utf-8?b?TMOhc3psw7Mg?= =?utf-8?b?w4lyc2Vr?= , Gerd Hoffmann , "Michael S. Tsirkin" Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" The boot framebuffer is expected to be configured by the firmware, so it uses fw_cfg as interface. Initialization goes as follows: (1) Check whenever etc/ramfb is present. (2) Allocate framebuffer from RAM. (3) Fill struct RAMFBCfg, write it to etc/ramfb. Done. You can write stuff to the framebuffer now, and it should appear automagically on the screen. Note that this isn't very efficient because it does a full display update on each refresh. No dirty tracking. Dirty tracking would have to be active for the whole ram slot, so that wouldn't be very efficient either. So it is *really* intended to be only active for a short time at boot, before the guest loaded the drivers for the real display hardware. This is the ramfb core code. Some windup is needed for display devices which want have a ramfb boot display. Signed-off-by: Gerd Hoffmann --- include/hw/display/ramfb.h | 8 ++++ hw/display/ramfb.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++ hw/display/Makefile.objs | 2 + 3 files changed, 105 insertions(+) create mode 100644 include/hw/display/ramfb.h create mode 100644 hw/display/ramfb.c diff --git a/include/hw/display/ramfb.h b/include/hw/display/ramfb.h new file mode 100644 index 0000000000..f3a772e99e --- /dev/null +++ b/include/hw/display/ramfb.h @@ -0,0 +1,8 @@ +#ifndef RAMFB_H +#define RAMFB_H + +typedef struct RAMFBState RAMFBState; +void ramfb_display_update(QemuConsole *con, RAMFBState *s); +RAMFBState *ramfb_setup(Error **errp); + +#endif /* RAMFB_H */ diff --git a/hw/display/ramfb.c b/hw/display/ramfb.c new file mode 100644 index 0000000000..5425e1feb1 --- /dev/null +++ b/hw/display/ramfb.c @@ -0,0 +1,95 @@ +/* + * early boot framebuffer in guest ram + * configured using fw_cfg + * + * Copyright Red Hat, Inc. 2017 + * + * Author: + * Gerd Hoffmann + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/loader.h" +#include "hw/display/ramfb.h" +#include "ui/console.h" +#include "sysemu/sysemu.h" + +struct RAMFBCfg { + uint64_t addr; + uint32_t fourcc; + uint32_t flags; + uint32_t width; + uint32_t height; + uint32_t stride; +}; + +struct RAMFBState { + DisplaySurface *ds; + uint32_t width, height; + struct RAMFBCfg cfg; +}; + +static void ramfb_fw_cfg_write(void *dev, off_t offset, size_t len) +{ + RAMFBState *s = dev; + void *framebuffer; + uint32_t stride, fourcc, format; + hwaddr addr, length; + + s->width = be32_to_cpu(s->cfg.width); + s->height = be32_to_cpu(s->cfg.height); + stride = be32_to_cpu(s->cfg.stride); + fourcc = be32_to_cpu(s->cfg.fourcc); + addr = be64_to_cpu(s->cfg.addr); + length = stride * s->height; + format = qemu_drm_format_to_pixman(fourcc); + + fprintf(stderr, "%s: %dx%d @ 0x%" PRIx64 "\n", __func__, + s->width, s->height, addr); + framebuffer = address_space_map(&address_space_memory, + addr, &length, false); + if (!framebuffer || length < stride * s->height) { + s->width = 0; + s->height = 0; + return; + } + s->ds = qemu_create_displaysurface_from(s->width, s->height, + format, stride, framebuffer); +} + +void ramfb_display_update(QemuConsole *con, RAMFBState *s) +{ + if (!s->width || !s->height) { + return; + } + + if (s->ds) { + dpy_gfx_replace_surface(con, s->ds); + s->ds = NULL; + } + + /* simple full screen update */ + dpy_gfx_update(con, 0, 0, s->width, s->height); +} + +RAMFBState *ramfb_setup(Error **errp) +{ + FWCfgState *fw_cfg = fw_cfg_find(); + RAMFBState *s; + + if (!fw_cfg || !fw_cfg->dma_enabled) { + error_setg(errp, "ramfb device requires fw_cfg with DMA"); + return NULL; + } + + s = g_new0(RAMFBState, 1); + + rom_add_vga("vgabios-ramfb.bin"); + fw_cfg_add_file_callback(fw_cfg, "etc/ramfb", + NULL, ramfb_fw_cfg_write, s, + &s->cfg, sizeof(s->cfg), false); + return s; +} diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs index 3c7c75b94d..fae17fd5ea 100644 --- a/hw/display/Makefile.objs +++ b/hw/display/Makefile.objs @@ -1,3 +1,5 @@ +common-obj-y += ramfb.o + common-obj-$(CONFIG_ADS7846) += ads7846.o common-obj-$(CONFIG_VGA_CIRRUS) += cirrus_vga.o common-obj-$(CONFIG_G364FB) += g364fb.o From patchwork Fri Mar 23 12:25:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 889961 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4072sB2XpHz9s0m for ; Fri, 23 Mar 2018 23:29:02 +1100 (AEDT) Received: from localhost ([::1]:37772 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ezLoZ-0008LE-80 for incoming@patchwork.ozlabs.org; Fri, 23 Mar 2018 08:28:59 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33951) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ezLlK-0005oj-84 for qemu-devel@nongnu.org; Fri, 23 Mar 2018 08:25:39 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ezLlI-0002O6-Jd for qemu-devel@nongnu.org; Fri, 23 Mar 2018 08:25:38 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:60664 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ezLlI-0002Nf-Et for qemu-devel@nongnu.org; Fri, 23 Mar 2018 08:25:36 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1EC54722CA for ; Fri, 23 Mar 2018 12:25:36 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-39.ams2.redhat.com [10.36.116.39]) by smtp.corp.redhat.com (Postfix) with ESMTP id C61A210B2B2B; Fri, 23 Mar 2018 12:25:21 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 3409199AF3; Fri, 23 Mar 2018 13:25:21 +0100 (CET) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Fri, 23 Mar 2018 13:25:17 +0100 Message-Id: <20180323122520.11270-5-kraxel@redhat.com> In-Reply-To: <20180323122520.11270-1-kraxel@redhat.com> References: <20180323122520.11270-1-kraxel@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Fri, 23 Mar 2018 12:25:36 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Fri, 23 Mar 2018 12:25:36 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kraxel@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v2 4/7] hw/display: add ramfb-testdev X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alex Williamson , =?utf-8?b?TMOhc3psw7Mg?= =?utf-8?b?w4lyc2Vr?= , Gerd Hoffmann , "Michael S. Tsirkin" Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Standalone device using ramfb. Intended for testing only. Offers optional logging of vga port access, for debugging purposes. Signed-off-by: Gerd Hoffmann --- hw/display/ramfb-testdev.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++ hw/display/Makefile.objs | 1 + 2 files changed, 97 insertions(+) create mode 100644 hw/display/ramfb-testdev.c diff --git a/hw/display/ramfb-testdev.c b/hw/display/ramfb-testdev.c new file mode 100644 index 0000000000..1e65cf4957 --- /dev/null +++ b/hw/display/ramfb-testdev.c @@ -0,0 +1,96 @@ +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/loader.h" +#include "hw/isa/isa.h" +#include "hw/display/ramfb.h" +#include "ui/console.h" +#include "sysemu/sysemu.h" + +#define TYPE_RAMFB "ramfb-testdev" +#define RAMFB(obj) OBJECT_CHECK(ISARAMFBState, (obj), TYPE_RAMFB) + +typedef struct ISARAMFBState { + ISADevice parent_obj; + QemuConsole *con; + RAMFBState *state; + PortioList vga_port_list; + bool vgalog; +} ISARAMFBState; + +/* log vga port activity, for trouble-shooting purposes */ +static uint32_t vga_log_read(void *opaque, uint32_t addr) +{ + fprintf(stderr, "%s: port 0x%x\n", __func__, addr); + return -1; +} + +static void vga_log_write(void *opaque, uint32_t addr, uint32_t val) +{ + fprintf(stderr, "%s: port 0x%x, value 0x%x\n", __func__, addr, val); +} + +static const MemoryRegionPortio vga_portio_list[] = { + { 0x04, 2, 1, .read = vga_log_read, .write = vga_log_write }, /* 3b4 */ + { 0x0a, 1, 1, .read = vga_log_read, .write = vga_log_write }, /* 3ba */ + { 0x10, 16, 1, .read = vga_log_read, .write = vga_log_write }, /* 3c0 */ + { 0x24, 2, 1, .read = vga_log_read, .write = vga_log_write }, /* 3d4 */ + { 0x2a, 1, 1, .read = vga_log_read, .write = vga_log_write }, /* 3da */ + PORTIO_END_OF_LIST(), +}; + +static void display_update_wrapper(void *dev) +{ + ISARAMFBState *ramfb = RAMFB(dev); + + if (0 /* native driver active */) { + /* non-test device would run native display update here */; + } else { + ramfb_display_update(ramfb->con, ramfb->state); + } +} + +static const GraphicHwOps wrapper_ops = { + .gfx_update = display_update_wrapper, +}; + +static void ramfb_realizefn(DeviceState *dev, Error **errp) +{ + ISARAMFBState *ramfb = RAMFB(dev); + + ramfb->con = graphic_console_init(dev, 0, &wrapper_ops, dev); + ramfb->state = ramfb_setup(errp); + + if (ramfb->vgalog) { + isa_register_portio_list(ISA_DEVICE(dev), &ramfb->vga_port_list, + 0x3b0, vga_portio_list, NULL, "log-vga"); + } +} + +static Property ramfb_properties[] = { + DEFINE_PROP_BOOL("vgalog", struct ISARAMFBState, vgalog, false), + DEFINE_PROP_END_OF_LIST(), +}; + +static void ramfb_class_initfn(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); + dc->realize = ramfb_realizefn; + dc->props = ramfb_properties; + dc->desc = "ram framebuffer test device"; +} + +static const TypeInfo ramfb_info = { + .name = TYPE_RAMFB, + .parent = TYPE_ISA_DEVICE, + .instance_size = sizeof(ISARAMFBState), + .class_init = ramfb_class_initfn, +}; + +static void ramfb_register_types(void) +{ + type_register_static(&ramfb_info); +} + +type_init(ramfb_register_types) diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs index fae17fd5ea..07d2f48782 100644 --- a/hw/display/Makefile.objs +++ b/hw/display/Makefile.objs @@ -1,4 +1,5 @@ common-obj-y += ramfb.o +common-obj-$(CONFIG_VGA_ISA) += ramfb-testdev.o common-obj-$(CONFIG_ADS7846) += ads7846.o common-obj-$(CONFIG_VGA_CIRRUS) += cirrus_vga.o From patchwork Fri Mar 23 12:25:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 889955 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4072p91f15z9s0b for ; Fri, 23 Mar 2018 23:26:25 +1100 (AEDT) Received: from localhost ([::1]:37758 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ezLm2-0005rA-Jo for incoming@patchwork.ozlabs.org; Fri, 23 Mar 2018 08:26:22 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33952) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ezLlK-0005ok-8a for qemu-devel@nongnu.org; Fri, 23 Mar 2018 08:25:39 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ezLlH-0002NH-M5 for qemu-devel@nongnu.org; Fri, 23 Mar 2018 08:25:38 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:60660 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ezLlH-0002Mg-HF for qemu-devel@nongnu.org; Fri, 23 Mar 2018 08:25:35 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2D85D722DC for ; Fri, 23 Mar 2018 12:25:35 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-39.ams2.redhat.com [10.36.116.39]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2C2D8D7E0D; Fri, 23 Mar 2018 12:25:28 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 3E1039B68B; Fri, 23 Mar 2018 13:25:21 +0100 (CET) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Fri, 23 Mar 2018 13:25:18 +0100 Message-Id: <20180323122520.11270-6-kraxel@redhat.com> In-Reply-To: <20180323122520.11270-1-kraxel@redhat.com> References: <20180323122520.11270-1-kraxel@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Fri, 23 Mar 2018 12:25:35 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Fri, 23 Mar 2018 12:25:35 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kraxel@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v2 5/7] hw/display: add virtio-ramfb X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alex Williamson , =?utf-8?b?TMOhc3psw7Mg?= =?utf-8?b?w4lyc2Vr?= , Gerd Hoffmann , "Michael S. Tsirkin" Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Like virtio-vga, but using ramfb instead of legacy vga. Signed-off-by: Gerd Hoffmann --- hw/display/virtio-ramfb.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++ hw/display/Makefile.objs | 2 +- 2 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 hw/display/virtio-ramfb.c diff --git a/hw/display/virtio-ramfb.c b/hw/display/virtio-ramfb.c new file mode 100644 index 0000000000..7611c16d39 --- /dev/null +++ b/hw/display/virtio-ramfb.c @@ -0,0 +1,149 @@ +#include "qemu/osdep.h" +#include "hw/hw.h" +#include "hw/pci/pci.h" +#include "ui/console.h" +#include "hw/virtio/virtio-pci.h" +#include "hw/display/ramfb.h" +#include "qapi/error.h" + +/* + * virtio-vga: This extends VirtioPCIProxy. + */ +#define TYPE_VIRTIO_RAMFB "virtio-ramfb" +#define VIRTIO_RAMFB(obj) \ + OBJECT_CHECK(VirtIORAMFB, (obj), TYPE_VIRTIO_RAMFB) + +typedef struct VirtIORAMFB { + VirtIOPCIProxy parent_obj; + VirtIOGPU vdev; + RAMFBState *ramfb; +} VirtIORAMFB; + +static void virtio_ramfb_invalidate_display(void *opaque) +{ + VirtIORAMFB *vramfb = opaque; + + if (vramfb->vdev.enable) { + virtio_gpu_ops.invalidate(&vramfb->vdev); + } +} + +static void virtio_ramfb_update_display(void *opaque) +{ + VirtIORAMFB *vramfb = opaque; + VirtIOGPU *g = &vramfb->vdev; + + if (vramfb->vdev.enable) { + virtio_gpu_ops.gfx_update(&vramfb->vdev); + } else { + ramfb_display_update(g->scanout[0].con, vramfb->ramfb); + } +} + +static int virtio_ramfb_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info) +{ + VirtIORAMFB *vramfb = opaque; + + if (virtio_gpu_ops.ui_info) { + return virtio_gpu_ops.ui_info(&vramfb->vdev, idx, info); + } + return -1; +} + +static void virtio_ramfb_gl_block(void *opaque, bool block) +{ + VirtIORAMFB *vramfb = opaque; + + if (virtio_gpu_ops.gl_block) { + virtio_gpu_ops.gl_block(&vramfb->vdev, block); + } +} + +static const GraphicHwOps virtio_ramfb_ops = { + .invalidate = virtio_ramfb_invalidate_display, + .gfx_update = virtio_ramfb_update_display, + .ui_info = virtio_ramfb_ui_info, + .gl_block = virtio_ramfb_gl_block, +}; + +static const VMStateDescription vmstate_virtio_ramfb = { + .name = "virtio-ramfb", + .version_id = 2, + .minimum_version_id = 2, + .fields = (VMStateField[]) { + /* no pci stuff here, saving the virtio device will handle that */ + /* FIXME */ + VMSTATE_END_OF_LIST() + } +}; + +/* RAMFB device wrapper around PCI device around virtio GPU */ +static void virtio_ramfb_realize(VirtIOPCIProxy *vpci_dev, Error **errp) +{ + VirtIORAMFB *vramfb = VIRTIO_RAMFB(vpci_dev); + VirtIOGPU *g = &vramfb->vdev; + Error *err = NULL; + int i; + + /* init virtio bits */ + qdev_set_parent_bus(DEVICE(g), BUS(&vpci_dev->bus)); + virtio_pci_force_virtio_1(vpci_dev); + object_property_set_bool(OBJECT(g), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + + /* add stdramfb mmio regions */ + vramfb->ramfb = ramfb_setup(errp); + graphic_console_set_hwops(g->scanout[0].con, &virtio_ramfb_ops, vramfb); + + for (i = 0; i < g->conf.max_outputs; i++) { + object_property_set_link(OBJECT(g->scanout[i].con), + OBJECT(vpci_dev), + "device", errp); + } +} + +static Property virtio_ramfb_properties[] = { + DEFINE_VIRTIO_GPU_PCI_PROPERTIES(VirtIOPCIProxy), + DEFINE_PROP_END_OF_LIST(), +}; + +static void virtio_ramfb_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); + PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); + + set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); + dc->props = virtio_ramfb_properties; + dc->vmsd = &vmstate_virtio_ramfb; + dc->hotpluggable = false; + + k->realize = virtio_ramfb_realize; + pcidev_k->class_id = PCI_CLASS_DISPLAY_OTHER; +} + +static void virtio_ramfb_inst_initfn(Object *obj) +{ + VirtIORAMFB *dev = VIRTIO_RAMFB(obj); + + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VIRTIO_GPU); +} + +static TypeInfo virtio_ramfb_info = { + .name = TYPE_VIRTIO_RAMFB, + .parent = TYPE_VIRTIO_PCI, + .instance_size = sizeof(struct VirtIORAMFB), + .instance_init = virtio_ramfb_inst_initfn, + .class_init = virtio_ramfb_class_init, +}; + +static void virtio_ramfb_register_types(void) +{ + type_register_static(&virtio_ramfb_info); +} + +type_init(virtio_ramfb_register_types) diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs index 07d2f48782..e71d9d2ca6 100644 --- a/hw/display/Makefile.objs +++ b/hw/display/Makefile.objs @@ -37,7 +37,7 @@ obj-$(CONFIG_VGA) += vga.o common-obj-$(CONFIG_QXL) += qxl.o qxl-logger.o qxl-render.o obj-$(CONFIG_VIRTIO) += virtio-gpu.o virtio-gpu-3d.o -obj-$(CONFIG_VIRTIO_PCI) += virtio-gpu-pci.o +obj-$(CONFIG_VIRTIO_PCI) += virtio-gpu-pci.o virtio-ramfb.o obj-$(CONFIG_VIRTIO_VGA) += virtio-vga.o virtio-gpu.o-cflags := $(VIRGL_CFLAGS) virtio-gpu.o-libs += $(VIRGL_LIBS) From patchwork Fri Mar 23 12:25:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 889963 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4072w76HBhz9s0m for ; Fri, 23 Mar 2018 23:31:35 +1100 (AEDT) Received: from localhost ([::1]:37801 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ezLr3-0003bt-CT for incoming@patchwork.ozlabs.org; Fri, 23 Mar 2018 08:31:33 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33993) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ezLlL-0005pP-Cc for qemu-devel@nongnu.org; Fri, 23 Mar 2018 08:25:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ezLlK-0002Py-14 for qemu-devel@nongnu.org; Fri, 23 Mar 2018 08:25:39 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:54378 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ezLlJ-0002PR-S9 for qemu-devel@nongnu.org; Fri, 23 Mar 2018 08:25:37 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8428A81A43A2 for ; Fri, 23 Mar 2018 12:25:37 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-39.ams2.redhat.com [10.36.116.39]) by smtp.corp.redhat.com (Postfix) with ESMTP id 22B102023231; Fri, 23 Mar 2018 12:25:35 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 52C139B691; Fri, 23 Mar 2018 13:25:21 +0100 (CET) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Fri, 23 Mar 2018 13:25:20 +0100 Message-Id: <20180323122520.11270-8-kraxel@redhat.com> In-Reply-To: <20180323122520.11270-1-kraxel@redhat.com> References: <20180323122520.11270-1-kraxel@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 23 Mar 2018 12:25:37 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 23 Mar 2018 12:25:37 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kraxel@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v2 7/7] [wip] hw/display: add qxl-ramfb X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alex Williamson , =?utf-8?b?TMOhc3psw7Mg?= =?utf-8?b?w4lyc2Vr?= , Gerd Hoffmann , "Michael S. Tsirkin" Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Like qxl-vga, but using ramfb instead of legacy vga. NOT WORKING YET. Also: Hackish proof-of-concept, with debug msgs. Signed-off-by: Gerd Hoffmann --- hw/display/qxl.h | 2 ++ hw/display/qxl.c | 47 +++++++++++++++++++++++++++++++++++++++++++---- ui/spice-display.c | 6 ++++++ 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/hw/display/qxl.h b/hw/display/qxl.h index 089696ef62..7bfdf429bf 100644 --- a/hw/display/qxl.h +++ b/hw/display/qxl.h @@ -5,6 +5,7 @@ #include "hw/hw.h" #include "hw/pci/pci.h" +#include "hw/display/ramfb.h" #include "vga_int.h" #include "qemu/thread.h" @@ -31,6 +32,7 @@ enum qxl_mode { typedef struct PCIQXLDevice { PCIDevice pci; + RAMFBState *ramfb; PortioList vga_port_list; SimpleSpiceDisplay ssd; int id; diff --git a/hw/display/qxl.c b/hw/display/qxl.c index a71714ccb4..ebe71fbcf5 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -1893,7 +1893,12 @@ static void qxl_hw_update(void *opaque) { PCIQXLDevice *qxl = opaque; - qxl_render_update(qxl); + if (qxl->mode == QXL_MODE_UNDEFINED && + qxl->ramfb != NULL) { + ramfb_display_update(qxl->vga.con, qxl->ramfb); + } else { + qxl_render_update(qxl); + } } static void qxl_dirty_one_surface(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, @@ -1968,7 +1973,8 @@ static void display_update(DisplayChangeListener *dcl, { PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl); - if (qxl->mode == QXL_MODE_VGA) { + if (qxl->mode == QXL_MODE_VGA || + (qxl->mode == QXL_MODE_UNDEFINED && qxl->ramfb)) { qemu_spice_display_update(&qxl->ssd, x, y, w, h); } } @@ -1979,7 +1985,9 @@ static void display_switch(DisplayChangeListener *dcl, PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl); qxl->ssd.ds = surface; - if (qxl->mode == QXL_MODE_VGA) { + if (qxl->mode == QXL_MODE_VGA || + (qxl->mode == QXL_MODE_UNDEFINED && qxl->ramfb)) { + fprintf(stderr, "%s: !native\n", __func__); qemu_spice_display_switch(&qxl->ssd, surface); } } @@ -1988,7 +1996,8 @@ static void display_refresh(DisplayChangeListener *dcl) { PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl); - if (qxl->mode == QXL_MODE_VGA) { + if (qxl->mode == QXL_MODE_VGA || + (qxl->mode == QXL_MODE_UNDEFINED && qxl->ramfb)) { qemu_spice_display_refresh(&qxl->ssd); } } @@ -2204,6 +2213,19 @@ static void qxl_realize_secondary(PCIDevice *dev, Error **errp) qxl_realize_common(qxl, errp); } +static void qxl_realize_ramfb(PCIDevice *dev, Error **errp) +{ + PCIQXLDevice *qxl = PCI_QXL(dev); + + qxl_realize_secondary(dev, errp); + qxl_hard_reset(qxl, 0); + + qxl->ramfb = ramfb_setup(errp); + qxl->ssd.dcl.ops = &display_listener_ops; + qxl->ssd.dcl.con = qxl->vga.con; + register_displaychangelistener(&qxl->ssd.dcl); +} + static int qxl_pre_save(void *opaque) { PCIQXLDevice* d = opaque; @@ -2472,11 +2494,28 @@ static const TypeInfo qxl_secondary_info = { .class_init = qxl_secondary_class_init, }; +static void qxl_ramfb_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->realize = qxl_realize_ramfb; + k->class_id = PCI_CLASS_DISPLAY_OTHER; + dc->desc = "Spice QXL GPU (ramfb)"; +} + +static const TypeInfo qxl_ramfb_info = { + .name = "qxl-ramfb", + .parent = TYPE_PCI_QXL, + .class_init = qxl_ramfb_class_init, +}; + static void qxl_register_types(void) { type_register_static(&qxl_pci_type_info); type_register_static(&qxl_primary_info); type_register_static(&qxl_secondary_info); + type_register_static(&qxl_ramfb_info); } type_init(qxl_register_types) diff --git a/ui/spice-display.c b/ui/spice-display.c index fe734821dd..c8082b0649 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -86,6 +86,9 @@ void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id, QXLDevSurfaceCreate *surface, qxl_async_io async) { + fprintf(stderr, "%s: %dx%d, %lx, %s\n", __func__, + surface->width, surface->height, (unsigned long)surface->mem, + (surface->group_id == MEMSLOT_GROUP_HOST) ? "host" : "guest"); trace_qemu_spice_create_primary_surface(ssd->qxl.id, id, surface, async); if (async != QXL_SYNC) { spice_qxl_create_primary_surface_async(&ssd->qxl, id, surface, @@ -310,6 +313,7 @@ void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd) { QXLDevMemSlot memslot; + fprintf(stderr, "%s:\n", __func__); memset(&memslot, 0, sizeof(memslot)); memslot.slot_group_id = MEMSLOT_GROUP_HOST; memslot.virt_end = ~0; @@ -343,6 +347,8 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd) surface.mem = (uintptr_t)ssd->buf; surface.group_id = MEMSLOT_GROUP_HOST; + fprintf(stderr, "%s: %dx%d @ %p\n", __func__, + surface.width, surface.height, ssd->buf); qemu_spice_create_primary_surface(ssd, 0, &surface, QXL_SYNC); }