diff options
Diffstat (limited to 'hw/display')
| -rw-r--r-- | hw/display/Makefile.objs | 4 | ||||
| -rw-r--r-- | hw/display/bcm2835_fb.c | 218 | ||||
| -rw-r--r-- | hw/display/cg3.c | 1 | ||||
| -rw-r--r-- | hw/display/cirrus_vga.c | 3 | ||||
| -rw-r--r-- | hw/display/exynos4210_fimd.c | 4 | ||||
| -rw-r--r-- | hw/display/g364fb.c | 2 | ||||
| -rw-r--r-- | hw/display/jazz_led.c | 3 | ||||
| -rw-r--r-- | hw/display/qxl.c | 1 | ||||
| -rw-r--r-- | hw/display/qxl.h | 1 | ||||
| -rw-r--r-- | hw/display/tc6393xb.c | 4 | ||||
| -rw-r--r-- | hw/display/vga-isa-mm.c | 60 | ||||
| -rw-r--r-- | hw/display/vga.c | 3 | ||||
| -rw-r--r-- | hw/display/virtio-gpu-3d.c | 8 | ||||
| -rw-r--r-- | hw/display/virtio-gpu.c | 59 | ||||
| -rw-r--r-- | hw/display/virtio-vga.c | 17 | ||||
| -rw-r--r-- | hw/display/vmware_vga.c | 5 | ||||
| -rw-r--r-- | hw/display/xlnx_dp.c | 3 |
17 files changed, 196 insertions, 200 deletions
diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs index fb8408c6d0..a606fb7404 100644 --- a/hw/display/Makefile.objs +++ b/hw/display/Makefile.objs @@ -1,5 +1,5 @@ -common-obj-y += ramfb.o -common-obj-y += ramfb-standalone.o +common-obj-$(CONFIG_FW_CFG_DMA) += ramfb.o +common-obj-$(CONFIG_FW_CFG_DMA) += ramfb-standalone.o common-obj-$(CONFIG_ADS7846) += ads7846.o common-obj-$(CONFIG_VGA_CIRRUS) += cirrus_vga.o diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c index 3355f4c131..d534d00a65 100644 --- a/hw/display/bcm2835_fb.c +++ b/hw/display/bcm2835_fb.c @@ -34,6 +34,13 @@ #define DEFAULT_VCRAM_SIZE 0x4000000 #define BCM2835_FB_OFFSET 0x00100000 +/* Maximum permitted framebuffer size; experimentally determined on an rpi2 */ +#define XRES_MAX 3840 +#define YRES_MAX 2560 +/* Framebuffer size used if guest requests zero size */ +#define XRES_SMALL 592 +#define YRES_SMALL 488 + static void fb_invalidate_display(void *opaque) { BCM2835FBState *s = BCM2835_FB(opaque); @@ -52,7 +59,7 @@ static void draw_line_src16(void *opaque, uint8_t *dst, const uint8_t *src, int bpp = surface_bits_per_pixel(surface); while (width--) { - switch (s->bpp) { + switch (s->config.bpp) { case 8: /* lookup palette starting at video ram base * TODO: cache translation, rather than doing this each time! @@ -91,7 +98,7 @@ static void draw_line_src16(void *opaque, uint8_t *dst, const uint8_t *src, break; } - if (s->pixo == 0) { + if (s->config.pixo == 0) { /* swap to BGR pixel format */ uint8_t tmp = r; r = b; @@ -126,6 +133,18 @@ static void draw_line_src16(void *opaque, uint8_t *dst, const uint8_t *src, } } +static bool fb_use_offsets(BCM2835FBConfig *config) +{ + /* + * Return true if we should use the viewport offsets. + * Experimentally, the hardware seems to do this only if the + * viewport size is larger than the physical screen. (It doesn't + * prevent the guest setting this silly viewport setting, though...) + */ + return config->xres_virtual > config->xres && + config->yres_virtual > config->yres; +} + static void fb_update_display(void *opaque) { BCM2835FBState *s = opaque; @@ -134,13 +153,19 @@ static void fb_update_display(void *opaque) int last = 0; int src_width = 0; int dest_width = 0; + uint32_t xoff = 0, yoff = 0; - if (s->lock || !s->xres) { + if (s->lock || !s->config.xres) { return; } - src_width = s->xres * (s->bpp >> 3); - dest_width = s->xres; + src_width = bcm2835_fb_get_pitch(&s->config); + if (fb_use_offsets(&s->config)) { + xoff = s->config.xoffset; + yoff = s->config.yoffset; + } + + dest_width = s->config.xres; switch (surface_bits_per_pixel(surface)) { case 0: @@ -165,89 +190,104 @@ static void fb_update_display(void *opaque) } if (s->invalidate) { - framebuffer_update_memory_section(&s->fbsection, s->dma_mr, s->base, - s->yres, src_width); + hwaddr base = s->config.base + xoff + yoff * src_width; + framebuffer_update_memory_section(&s->fbsection, s->dma_mr, + base, + s->config.yres, src_width); } - framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres, + framebuffer_update_display(surface, &s->fbsection, + s->config.xres, s->config.yres, src_width, dest_width, 0, s->invalidate, draw_line_src16, s, &first, &last); if (first >= 0) { - dpy_gfx_update(s->con, 0, first, s->xres, last - first + 1); + dpy_gfx_update(s->con, 0, first, s->config.xres, + last - first + 1); } s->invalidate = false; } -static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value) +void bcm2835_fb_validate_config(BCM2835FBConfig *config) { - value &= ~0xf; - - s->lock = true; - - s->xres = ldl_le_phys(&s->dma_as, value); - s->yres = ldl_le_phys(&s->dma_as, value + 4); - s->xres_virtual = ldl_le_phys(&s->dma_as, value + 8); - s->yres_virtual = ldl_le_phys(&s->dma_as, value + 12); - s->bpp = ldl_le_phys(&s->dma_as, value + 20); - s->xoffset = ldl_le_phys(&s->dma_as, value + 24); - s->yoffset = ldl_le_phys(&s->dma_as, value + 28); - - s->base = s->vcram_base | (value & 0xc0000000); - s->base += BCM2835_FB_OFFSET; + /* + * Validate the config, and clip any bogus values into range, + * as the hardware does. Note that fb_update_display() relies on + * this happening to prevent it from performing out-of-range + * accesses on redraw. + */ + config->xres = MIN(config->xres, XRES_MAX); + config->xres_virtual = MIN(config->xres_virtual, XRES_MAX); + config->yres = MIN(config->yres, YRES_MAX); + config->yres_virtual = MIN(config->yres_virtual, YRES_MAX); + + /* + * These are not minima: a 40x40 framebuffer will be accepted. + * They're only used as defaults if the guest asks for zero size. + */ + if (config->xres == 0) { + config->xres = XRES_SMALL; + } + if (config->yres == 0) { + config->yres = YRES_SMALL; + } + if (config->xres_virtual == 0) { + config->xres_virtual = config->xres; + } + if (config->yres_virtual == 0) { + config->yres_virtual = config->yres; + } - /* TODO - Manage properly virtual resolution */ + if (fb_use_offsets(config)) { + /* Clip the offsets so the viewport is within the physical screen */ + config->xoffset = MIN(config->xoffset, + config->xres_virtual - config->xres); + config->yoffset = MIN(config->yoffset, + config->yres_virtual - config->yres); + } +} - s->pitch = s->xres * (s->bpp >> 3); - s->size = s->yres * s->pitch; +void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig) +{ + s->lock = true; - stl_le_phys(&s->dma_as, value + 16, s->pitch); - stl_le_phys(&s->dma_as, value + 32, s->base); - stl_le_phys(&s->dma_as, value + 36, s->size); + s->config = *newconfig; s->invalidate = true; - qemu_console_resize(s->con, s->xres, s->yres); + qemu_console_resize(s->con, s->config.xres, s->config.yres); s->lock = false; } -void bcm2835_fb_reconfigure(BCM2835FBState *s, uint32_t *xres, uint32_t *yres, - uint32_t *xoffset, uint32_t *yoffset, uint32_t *bpp, - uint32_t *pixo, uint32_t *alpha) +static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value) { - s->lock = true; + uint32_t pitch; + uint32_t size; + BCM2835FBConfig newconf; - /* TODO: input validation! */ - if (xres) { - s->xres = *xres; - } - if (yres) { - s->yres = *yres; - } - if (xoffset) { - s->xoffset = *xoffset; - } - if (yoffset) { - s->yoffset = *yoffset; - } - if (bpp) { - s->bpp = *bpp; - } - if (pixo) { - s->pixo = *pixo; - } - if (alpha) { - s->alpha = *alpha; - } + value &= ~0xf; - /* TODO - Manage properly virtual resolution */ + newconf.xres = ldl_le_phys(&s->dma_as, value); + newconf.yres = ldl_le_phys(&s->dma_as, value + 4); + newconf.xres_virtual = ldl_le_phys(&s->dma_as, value + 8); + newconf.yres_virtual = ldl_le_phys(&s->dma_as, value + 12); + newconf.bpp = ldl_le_phys(&s->dma_as, value + 20); + newconf.xoffset = ldl_le_phys(&s->dma_as, value + 24); + newconf.yoffset = ldl_le_phys(&s->dma_as, value + 28); - s->pitch = s->xres * (s->bpp >> 3); - s->size = s->yres * s->pitch; + newconf.base = s->vcram_base | (value & 0xc0000000); + newconf.base += BCM2835_FB_OFFSET; - s->invalidate = true; - qemu_console_resize(s->con, s->xres, s->yres); - s->lock = false; + bcm2835_fb_validate_config(&newconf); + + pitch = bcm2835_fb_get_pitch(&newconf); + size = bcm2835_fb_get_size(&newconf); + + stl_le_phys(&s->dma_as, value + 16, pitch); + stl_le_phys(&s->dma_as, value + 32, newconf.base); + stl_le_phys(&s->dma_as, value + 36, size); + + bcm2835_fb_reconfigure(s, &newconf); } static uint64_t bcm2835_fb_read(void *opaque, hwaddr offset, unsigned size) @@ -312,18 +352,17 @@ static const VMStateDescription vmstate_bcm2835_fb = { VMSTATE_BOOL(lock, BCM2835FBState), VMSTATE_BOOL(invalidate, BCM2835FBState), VMSTATE_BOOL(pending, BCM2835FBState), - VMSTATE_UINT32(xres, BCM2835FBState), - VMSTATE_UINT32(yres, BCM2835FBState), - VMSTATE_UINT32(xres_virtual, BCM2835FBState), - VMSTATE_UINT32(yres_virtual, BCM2835FBState), - VMSTATE_UINT32(xoffset, BCM2835FBState), - VMSTATE_UINT32(yoffset, BCM2835FBState), - VMSTATE_UINT32(bpp, BCM2835FBState), - VMSTATE_UINT32(base, BCM2835FBState), - VMSTATE_UINT32(pitch, BCM2835FBState), - VMSTATE_UINT32(size, BCM2835FBState), - VMSTATE_UINT32(pixo, BCM2835FBState), - VMSTATE_UINT32(alpha, BCM2835FBState), + VMSTATE_UINT32(config.xres, BCM2835FBState), + VMSTATE_UINT32(config.yres, BCM2835FBState), + VMSTATE_UINT32(config.xres_virtual, BCM2835FBState), + VMSTATE_UINT32(config.yres_virtual, BCM2835FBState), + VMSTATE_UINT32(config.xoffset, BCM2835FBState), + VMSTATE_UINT32(config.yoffset, BCM2835FBState), + VMSTATE_UINT32(config.bpp, BCM2835FBState), + VMSTATE_UINT32(config.base, BCM2835FBState), + VMSTATE_UNUSED(8), /* Was pitch and size */ + VMSTATE_UINT32(config.pixo, BCM2835FBState), + VMSTATE_UINT32(config.alpha, BCM2835FBState), VMSTATE_END_OF_LIST() } }; @@ -349,13 +388,7 @@ static void bcm2835_fb_reset(DeviceState *dev) s->pending = false; - s->xres_virtual = s->xres; - s->yres_virtual = s->yres; - s->xoffset = 0; - s->yoffset = 0; - s->base = s->vcram_base + BCM2835_FB_OFFSET; - s->pitch = s->xres * (s->bpp >> 3); - s->size = s->yres * s->pitch; + s->config = s->initial_config; s->invalidate = true; s->lock = false; @@ -379,24 +412,33 @@ static void bcm2835_fb_realize(DeviceState *dev, Error **errp) return; } + /* Fill in the parts of initial_config that are not set by QOM properties */ + s->initial_config.xres_virtual = s->initial_config.xres; + s->initial_config.yres_virtual = s->initial_config.yres; + s->initial_config.xoffset = 0; + s->initial_config.yoffset = 0; + s->initial_config.base = s->vcram_base + BCM2835_FB_OFFSET; + s->dma_mr = MEMORY_REGION(obj); address_space_init(&s->dma_as, s->dma_mr, NULL); bcm2835_fb_reset(dev); s->con = graphic_console_init(dev, 0, &vgafb_ops, s); - qemu_console_resize(s->con, s->xres, s->yres); + qemu_console_resize(s->con, s->config.xres, s->config.yres); } static Property bcm2835_fb_props[] = { DEFINE_PROP_UINT32("vcram-base", BCM2835FBState, vcram_base, 0),/*required*/ DEFINE_PROP_UINT32("vcram-size", BCM2835FBState, vcram_size, DEFAULT_VCRAM_SIZE), - DEFINE_PROP_UINT32("xres", BCM2835FBState, xres, 640), - DEFINE_PROP_UINT32("yres", BCM2835FBState, yres, 480), - DEFINE_PROP_UINT32("bpp", BCM2835FBState, bpp, 16), - DEFINE_PROP_UINT32("pixo", BCM2835FBState, pixo, 1), /* 1=RGB, 0=BGR */ - DEFINE_PROP_UINT32("alpha", BCM2835FBState, alpha, 2), /* alpha ignored */ + DEFINE_PROP_UINT32("xres", BCM2835FBState, initial_config.xres, 640), + DEFINE_PROP_UINT32("yres", BCM2835FBState, initial_config.yres, 480), + DEFINE_PROP_UINT32("bpp", BCM2835FBState, initial_config.bpp, 16), + DEFINE_PROP_UINT32("pixo", BCM2835FBState, + initial_config.pixo, 1), /* 1=RGB, 0=BGR */ + DEFINE_PROP_UINT32("alpha", BCM2835FBState, + initial_config.alpha, 2), /* alpha ignored */ DEFINE_PROP_END_OF_LIST() }; diff --git a/hw/display/cg3.c b/hw/display/cg3.c index 6fff4852c5..1c199ab369 100644 --- a/hw/display/cg3.c +++ b/hw/display/cg3.c @@ -232,6 +232,7 @@ static void cg3_reg_write(void *opaque, hwaddr addr, uint64_t val, s->b[s->dac_index] = regval; /* Index autoincrement */ s->dac_index = (s->dac_index + 1) & 0xff; + /* fall through */ default: s->dac_state = 0; break; diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index 7583b18c29..04c87c8e8d 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -1426,7 +1426,8 @@ static void cirrus_vga_write_sr(CirrusVGAState * s, uint32_t val) s->vga.hw_cursor_y = (val << 3) | (s->vga.sr_index >> 5); break; case 0x07: // Extended Sequencer Mode - cirrus_update_memory_access(s); + cirrus_update_memory_access(s); + /* fall through */ case 0x08: // EEPROM Control case 0x09: // Scratch Register 0 case 0x0a: // Scratch Register 1 diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c index f011ea5b00..083b3172da 100644 --- a/hw/display/exynos4210_fimd.c +++ b/hw/display/exynos4210_fimd.c @@ -1272,8 +1272,6 @@ static void exynos4210_fimd_update(void *opaque) uint8_t *host_fb_addr; bool is_dirty = false; const int global_width = (s->vidtcon[2] & FIMD_VIDTCON2_SIZE_MASK) + 1; - const int global_height = ((s->vidtcon[2] >> FIMD_VIDTCON2_VER_SHIFT) & - FIMD_VIDTCON2_SIZE_MASK) + 1; if (!s || !s->console || !s->enabled || surface_bits_per_pixel(qemu_console_surface(s->console)) == 0) { @@ -1329,7 +1327,7 @@ static void exynos4210_fimd_update(void *opaque) fimd_copy_line_toqemu(global_width, s->ifb + global_width * line * RGBA_SIZE, d + global_width * line * bpp); } - dpy_gfx_update(s->console, 0, 0, global_width, global_height); + dpy_gfx_update_full(s->console); } s->invalidate = false; s->vidintcon[1] |= FIMD_VIDINT_INTFRMPEND; diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c index fbc2b2422d..8ad7e5d824 100644 --- a/hw/display/g364fb.c +++ b/hw/display/g364fb.c @@ -229,7 +229,7 @@ static void g364fb_draw_blank(G364State *s) d += surface_stride(surface); } - dpy_gfx_update(s->con, 0, 0, s->width, s->height); + dpy_gfx_update_full(s->con); s->blanked = 1; } diff --git a/hw/display/jazz_led.c b/hw/display/jazz_led.c index 3c97d56434..eb7933d2a3 100644 --- a/hw/display/jazz_led.c +++ b/hw/display/jazz_led.c @@ -214,8 +214,7 @@ static void jazz_led_update_display(void *opaque) } s->state = REDRAW_NONE; - dpy_gfx_update(s->con, 0, 0, - surface_width(surface), surface_height(surface)); + dpy_gfx_update_full(s->con); } static void jazz_led_invalidate_display(void *opaque) diff --git a/hw/display/qxl.c b/hw/display/qxl.c index 830c392c53..8e9135d9c6 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -2057,7 +2057,6 @@ static void qxl_realize_common(PCIQXLDevice *qxl, Error **errp) qemu_spice_display_init_common(&qxl->ssd); qxl->mode = QXL_MODE_UNDEFINED; - qxl->generation = 1; qxl->num_memslots = NUM_MEMSLOTS; qemu_mutex_init(&qxl->track_lock); qemu_mutex_init(&qxl->async_lock); diff --git a/hw/display/qxl.h b/hw/display/qxl.h index 089696ef62..6eacba080d 100644 --- a/hw/display/qxl.h +++ b/hw/display/qxl.h @@ -43,7 +43,6 @@ typedef struct PCIQXLDevice { enum qxl_mode mode; uint32_t cmdflags; - int generation; uint32_t revision; int32_t num_memslots; diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c index 8392e59493..3360be6f84 100644 --- a/hw/display/tc6393xb.c +++ b/hw/display/tc6393xb.c @@ -461,7 +461,7 @@ static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update) return; } - dpy_gfx_update(s->con, 0, 0, s->scr_width, s->scr_height); + dpy_gfx_update_full(s->con); } static void tc6393xb_draw_blank(TC6393xbState *s, int full_update) @@ -480,7 +480,7 @@ static void tc6393xb_draw_blank(TC6393xbState *s, int full_update) d += surface_stride(surface); } - dpy_gfx_update(s->con, 0, 0, s->scr_width, s->scr_height); + dpy_gfx_update_full(s->con); } static void tc6393xb_update_display(void *opaque) diff --git a/hw/display/vga-isa-mm.c b/hw/display/vga-isa-mm.c index 232216cad0..215e649719 100644 --- a/hw/display/vga-isa-mm.c +++ b/hw/display/vga-isa-mm.c @@ -36,64 +36,30 @@ typedef struct ISAVGAMMState { } ISAVGAMMState; /* Memory mapped interface */ -static uint32_t vga_mm_readb (void *opaque, hwaddr addr) +static uint64_t vga_mm_read(void *opaque, hwaddr addr, unsigned size) { ISAVGAMMState *s = opaque; - return vga_ioport_read(&s->vga, addr >> s->it_shift) & 0xff; + return vga_ioport_read(&s->vga, addr >> s->it_shift) & + MAKE_64BIT_MASK(0, size * 8); } -static void vga_mm_writeb (void *opaque, - hwaddr addr, uint32_t value) +static void vga_mm_write(void *opaque, hwaddr addr, uint64_t value, + unsigned size) { ISAVGAMMState *s = opaque; - vga_ioport_write(&s->vga, addr >> s->it_shift, value & 0xff); -} - -static uint32_t vga_mm_readw (void *opaque, hwaddr addr) -{ - ISAVGAMMState *s = opaque; - - return vga_ioport_read(&s->vga, addr >> s->it_shift) & 0xffff; -} - -static void vga_mm_writew (void *opaque, - hwaddr addr, uint32_t value) -{ - ISAVGAMMState *s = opaque; - - vga_ioport_write(&s->vga, addr >> s->it_shift, value & 0xffff); -} - -static uint32_t vga_mm_readl (void *opaque, hwaddr addr) -{ - ISAVGAMMState *s = opaque; - - return vga_ioport_read(&s->vga, addr >> s->it_shift); -} - -static void vga_mm_writel (void *opaque, - hwaddr addr, uint32_t value) -{ - ISAVGAMMState *s = opaque; - - vga_ioport_write(&s->vga, addr >> s->it_shift, value); + vga_ioport_write(&s->vga, addr >> s->it_shift, + value & MAKE_64BIT_MASK(0, size * 8)); } static const MemoryRegionOps vga_mm_ctrl_ops = { - .old_mmio = { - .read = { - vga_mm_readb, - vga_mm_readw, - vga_mm_readl, - }, - .write = { - vga_mm_writeb, - vga_mm_writew, - vga_mm_writel, - }, - }, + .read = vga_mm_read, + .write = vga_mm_write, + .valid.min_access_size = 1, + .valid.max_access_size = 4, + .impl.min_access_size = 1, + .impl.max_access_size = 4, .endianness = DEVICE_NATIVE_ENDIAN, }; diff --git a/hw/display/vga.c b/hw/display/vga.c index 802cfd47db..3ba3f6853c 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -1745,8 +1745,7 @@ static void vga_draw_blank(VGACommonState *s, int full_update) memset(d, 0, w); d += surface_stride(surface); } - dpy_gfx_update(s->con, 0, 0, - s->last_scr_width, s->last_scr_height); + dpy_gfx_update_full(s->con); } #define GMODE_TEXT 0 diff --git a/hw/display/virtio-gpu-3d.c b/hw/display/virtio-gpu-3d.c index 3558f38fe8..55d76405a9 100644 --- a/hw/display/virtio-gpu-3d.c +++ b/hw/display/virtio-gpu-3d.c @@ -86,7 +86,7 @@ static void virgl_cmd_resource_unref(VirtIOGPU *g, &res_iovs, &num_iovs); if (res_iovs != NULL && num_iovs != 0) { - virtio_gpu_cleanup_mapping_iov(res_iovs, num_iovs); + virtio_gpu_cleanup_mapping_iov(g, res_iovs, num_iovs); } virgl_renderer_resource_unref(unref.resource_id); } @@ -291,7 +291,7 @@ static void virgl_resource_attach_backing(VirtIOGPU *g, VIRTIO_GPU_FILL_CMD(att_rb); trace_virtio_gpu_cmd_res_back_attach(att_rb.resource_id); - ret = virtio_gpu_create_mapping_iov(&att_rb, cmd, NULL, &res_iovs); + ret = virtio_gpu_create_mapping_iov(g, &att_rb, cmd, NULL, &res_iovs); if (ret != 0) { cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; return; @@ -301,7 +301,7 @@ static void virgl_resource_attach_backing(VirtIOGPU *g, res_iovs, att_rb.nr_entries); if (ret != 0) - virtio_gpu_cleanup_mapping_iov(res_iovs, att_rb.nr_entries); + virtio_gpu_cleanup_mapping_iov(g, res_iovs, att_rb.nr_entries); } static void virgl_resource_detach_backing(VirtIOGPU *g, @@ -320,7 +320,7 @@ static void virgl_resource_detach_backing(VirtIOGPU *g, if (res_iovs == NULL || num_iovs == 0) { return; } - virtio_gpu_cleanup_mapping_iov(res_iovs, num_iovs); + virtio_gpu_cleanup_mapping_iov(g, res_iovs, num_iovs); } diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index 3ddd29c0de..7be3a9d404 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -17,6 +17,7 @@ #include "qemu/iov.h" #include "ui/console.h" #include "trace.h" +#include "sysemu/dma.h" #include "hw/virtio/virtio.h" #include "hw/virtio/virtio-gpu.h" #include "hw/virtio/virtio-bus.h" @@ -29,7 +30,8 @@ static struct virtio_gpu_simple_resource* virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id); -static void virtio_gpu_cleanup_mapping(struct virtio_gpu_simple_resource *res); +static void virtio_gpu_cleanup_mapping(VirtIOGPU *g, + struct virtio_gpu_simple_resource *res); static void virtio_gpu_ctrl_hdr_bswap(struct virtio_gpu_ctrl_hdr *hdr) @@ -421,11 +423,6 @@ static void virtio_gpu_disable_scanout(VirtIOGPU *g, int scanout_id) scanout->height ?: 480, "Guest disabled display."); } - - if (g->disable_scanout) { - g->disable_scanout(g, scanout_id); - } - dpy_gfx_replace_surface(scanout->con, ds); scanout->resource_id = 0; scanout->ds = NULL; @@ -447,7 +444,7 @@ static void virtio_gpu_resource_destroy(VirtIOGPU *g, } pixman_image_unref(res->image); - virtio_gpu_cleanup_mapping(res); + virtio_gpu_cleanup_mapping(g, res); QTAILQ_REMOVE(&g->reslist, res, next); g->hostmem -= res->hostmem; g_free(res); @@ -693,7 +690,8 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g, scanout->height = ss.r.height; } -int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab, +int virtio_gpu_create_mapping_iov(VirtIOGPU *g, + struct virtio_gpu_resource_attach_backing *ab, struct virtio_gpu_ctrl_command *cmd, uint64_t **addr, struct iovec **iov) { @@ -729,7 +727,8 @@ int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab, uint32_t l = le32_to_cpu(ents[i].length); hwaddr len = l; (*iov)[i].iov_len = l; - (*iov)[i].iov_base = cpu_physical_memory_map(a, &len, 1); + (*iov)[i].iov_base = dma_memory_map(VIRTIO_DEVICE(g)->dma_as, + a, &len, DMA_DIRECTION_TO_DEVICE); if (addr) { (*addr)[i] = a; } @@ -737,7 +736,7 @@ int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab, qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for" " resource %d element %d\n", __func__, ab->resource_id, i); - virtio_gpu_cleanup_mapping_iov(*iov, i); + virtio_gpu_cleanup_mapping_iov(g, *iov, i); g_free(ents); *iov = NULL; if (addr) { @@ -751,20 +750,24 @@ int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab, return 0; } -void virtio_gpu_cleanup_mapping_iov(struct iovec *iov, uint32_t count) +void virtio_gpu_cleanup_mapping_iov(VirtIOGPU *g, + struct iovec *iov, uint32_t count) { int i; for (i = 0; i < count; i++) { - cpu_physical_memory_unmap(iov[i].iov_base, iov[i].iov_len, 1, - iov[i].iov_len); + dma_memory_unmap(VIRTIO_DEVICE(g)->dma_as, + iov[i].iov_base, iov[i].iov_len, + DMA_DIRECTION_TO_DEVICE, + iov[i].iov_len); } g_free(iov); } -static void virtio_gpu_cleanup_mapping(struct virtio_gpu_simple_resource *res) +static void virtio_gpu_cleanup_mapping(VirtIOGPU *g, + struct virtio_gpu_simple_resource *res) { - virtio_gpu_cleanup_mapping_iov(res->iov, res->iov_cnt); + virtio_gpu_cleanup_mapping_iov(g, res->iov, res->iov_cnt); res->iov = NULL; res->iov_cnt = 0; g_free(res->addrs); @@ -796,7 +799,7 @@ virtio_gpu_resource_attach_backing(VirtIOGPU *g, return; } - ret = virtio_gpu_create_mapping_iov(&ab, cmd, &res->addrs, &res->iov); + ret = virtio_gpu_create_mapping_iov(g, &ab, cmd, &res->addrs, &res->iov); if (ret != 0) { cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; return; @@ -823,7 +826,7 @@ virtio_gpu_resource_detach_backing(VirtIOGPU *g, cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; return; } - virtio_gpu_cleanup_mapping(res); + virtio_gpu_cleanup_mapping(g, res); } static void virtio_gpu_simple_process_cmd(VirtIOGPU *g, @@ -1148,16 +1151,21 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size, for (i = 0; i < res->iov_cnt; i++) { hwaddr len = res->iov[i].iov_len; res->iov[i].iov_base = - cpu_physical_memory_map(res->addrs[i], &len, 1); + dma_memory_map(VIRTIO_DEVICE(g)->dma_as, + res->addrs[i], &len, DMA_DIRECTION_TO_DEVICE); + if (!res->iov[i].iov_base || len != res->iov[i].iov_len) { /* Clean up the half-a-mapping we just created... */ if (res->iov[i].iov_base) { - cpu_physical_memory_unmap(res->iov[i].iov_base, - len, 0, 0); + dma_memory_unmap(VIRTIO_DEVICE(g)->dma_as, + res->iov[i].iov_base, + res->iov[i].iov_len, + DMA_DIRECTION_TO_DEVICE, + res->iov[i].iov_len); } /* ...and the mappings for previous loop iterations */ res->iov_cnt = i; - virtio_gpu_cleanup_mapping(res); + virtio_gpu_cleanup_mapping(g, res); pixman_image_unref(res->image); g_free(res); return -EINVAL; @@ -1187,7 +1195,7 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size, } dpy_gfx_replace_surface(scanout->con, scanout->ds); - dpy_gfx_update(scanout->con, 0, 0, scanout->width, scanout->height); + dpy_gfx_update_full(scanout->con); if (scanout->cursor.resource_id) { update_cursor(g, &scanout->cursor); } @@ -1205,11 +1213,6 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp) Error *local_err = NULL; int i; - if (virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM)) { - error_setg(errp, "virtio-gpu does not support vIOMMU yet"); - return; - } - if (g->conf.max_outputs > VIRTIO_GPU_MAX_SCANOUTS) { error_setg(errp, "invalid max_outputs > %d", VIRTIO_GPU_MAX_SCANOUTS); return; @@ -1289,7 +1292,7 @@ static void virtio_gpu_instance_init(Object *obj) { } -static void virtio_gpu_reset(VirtIODevice *vdev) +void virtio_gpu_reset(VirtIODevice *vdev) { VirtIOGPU *g = VIRTIO_GPU(vdev); struct virtio_gpu_simple_resource *res, *tmp; diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c index 701d980872..1e601c1a3b 100644 --- a/hw/display/virtio-vga.c +++ b/hw/display/virtio-vga.c @@ -75,16 +75,6 @@ static void virtio_vga_gl_block(void *opaque, bool block) } } -static void virtio_vga_disable_scanout(VirtIOGPU *g, int scanout_id) -{ - VirtIOVGA *vvga = container_of(g, VirtIOVGA, vdev); - - if (scanout_id == 0) { - /* reset surface if needed */ - vvga->vga.graphic_mode = -1; - } -} - static const GraphicHwOps virtio_vga_ops = { .invalidate = virtio_vga_invalidate_display, .gfx_update = virtio_vga_update_display, @@ -166,7 +156,6 @@ static void virtio_vga_realize(VirtIOPCIProxy *vpci_dev, Error **errp) vvga->vga_mrs, true); vga->con = g->scanout[0].con; - g->disable_scanout = virtio_vga_disable_scanout; graphic_console_set_hwops(vga->con, &virtio_vga_ops, vvga); for (i = 0; i < g->conf.max_outputs; i++) { @@ -179,8 +168,12 @@ static void virtio_vga_realize(VirtIOPCIProxy *vpci_dev, Error **errp) static void virtio_vga_reset(DeviceState *dev) { VirtIOVGA *vvga = VIRTIO_VGA(dev); - vvga->vdev.enable = 0; + /* reset virtio-gpu */ + virtio_gpu_reset(VIRTIO_DEVICE(&vvga->vdev)); + + /* reset vga */ + vga_common_reset(&vvga->vga); vga_dirty_log_start(&vvga->vga); } diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c index 0bbb78b9a6..afbf1c5973 100644 --- a/hw/display/vmware_vga.c +++ b/hw/display/vmware_vga.c @@ -1116,7 +1116,6 @@ static inline void vmsvga_check_size(struct vmsvga_state_s *s) static void vmsvga_update_display(void *opaque) { struct vmsvga_state_s *s = opaque; - DisplaySurface *surface; if (!s->enable || !s->config) { /* in standard vga mode */ @@ -1125,15 +1124,13 @@ static void vmsvga_update_display(void *opaque) } vmsvga_check_size(s); - surface = qemu_console_surface(s->vga.con); vmsvga_fifo_run(s); vmsvga_update_rect_flush(s); if (s->invalidated) { s->invalidated = 0; - dpy_gfx_update(s->vga.con, 0, 0, - surface_width(surface), surface_height(surface)); + dpy_gfx_update_full(s->vga.con); } } diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c index 6439bd05ef..cc0f9bc9cc 100644 --- a/hw/display/xlnx_dp.c +++ b/hw/display/xlnx_dp.c @@ -1186,8 +1186,7 @@ static void xlnx_dp_update_display(void *opaque) /* * XXX: We might want to update only what changed. */ - dpy_gfx_update(s->console, 0, 0, surface_width(s->g_plane.surface), - surface_height(s->g_plane.surface)); + dpy_gfx_update_full(s->console); } static const GraphicHwOps xlnx_dp_gfx_ops = { |