return true;
}
-static void dpy_refresh(DisplayState *s)
+/*
+ * Safe DPY refresh for TCG guests. We use the exclusive mechanism to
+ * ensure the TCG vCPUs are quiescent so we can avoid races between
+ * dirty page tracking for direct frame-buffer access by the guest.
+ *
+ * This is a temporary stopgap until we've fixed the dirty tracking
+ * races in display adapters.
+ */
+static void do_safe_dpy_refresh(DisplayChangeListener *dcl)
{
- DisplayChangeListener *dcl;
-
- QLIST_FOREACH(dcl, &s->listeners, next) {
- if (dcl->ops->dpy_refresh) {
- dcl->ops->dpy_refresh(dcl);
- }
- }
+ qemu_mutex_unlock_iothread();
+ start_exclusive();
+ qemu_mutex_lock_iothread();
+ dcl->ops->dpy_refresh(dcl);
+ qemu_mutex_unlock_iothread();
+ end_exclusive();
+ qemu_mutex_lock_iothread();
}
-void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
- int dst_x, int dst_y, int w, int h)
+static void dpy_refresh(DisplayState *s)
{
- DisplayState *s = con->ds;
DisplayChangeListener *dcl;
- if (!qemu_console_is_visible(con)) {
- return;
- }
QLIST_FOREACH(dcl, &s->listeners, next) {
- if (con != (dcl->con ? dcl->con : active_console)) {
- continue;
- }
- if (dcl->ops->dpy_gfx_copy) {
- dcl->ops->dpy_gfx_copy(dcl, src_x, src_y, dst_x, dst_y, w, h);
- } else { /* TODO */
- dcl->ops->dpy_gfx_update(dcl, dst_x, dst_y, w, h);
+ if (dcl->ops->dpy_refresh) {
+ if (tcg_enabled()) {
+ do_safe_dpy_refresh(dcl);
+ } else {
+ dcl->ops->dpy_refresh(dcl);
+ }
}
}
}
return con->gl->ops->dpy_gl_ctx_get_current(con->gl);
}
-void dpy_gl_scanout(QemuConsole *con,
- uint32_t backing_id, bool backing_y_0_top,
- uint32_t backing_width, uint32_t backing_height,
- uint32_t x, uint32_t y, uint32_t width, uint32_t height)
+void dpy_gl_scanout_disable(QemuConsole *con)
+{
+ assert(con->gl);
+ if (con->gl->ops->dpy_gl_scanout_disable) {
+ con->gl->ops->dpy_gl_scanout_disable(con->gl);
+ } else {
+ con->gl->ops->dpy_gl_scanout_texture(con->gl, 0, false, 0, 0,
+ 0, 0, 0, 0);
+ }
+}
+
+void dpy_gl_scanout_texture(QemuConsole *con,
+ uint32_t backing_id,
+ bool backing_y_0_top,
+ uint32_t backing_width,
+ uint32_t backing_height,
+ uint32_t x, uint32_t y,
+ uint32_t width, uint32_t height)
{
assert(con->gl);
- con->gl->ops->dpy_gl_scanout(con->gl, backing_id,
- backing_y_0_top,
- backing_width, backing_height,
- x, y, width, height);
+ con->gl->ops->dpy_gl_scanout_texture(con->gl, backing_id,
+ backing_y_0_top,
+ backing_width, backing_height,
+ x, y, width, height);
}
void dpy_gl_update(QemuConsole *con,
qemu_chr_be_generic_open(chr);
}
-static const CharDriver vc_driver;
-
static void vc_chr_open(Chardev *chr,
ChardevBackend *backend,
bool *be_opened,
dpy_gfx_replace_surface(s, surface);
}
-void qemu_console_copy(QemuConsole *con, int src_x, int src_y,
- int dst_x, int dst_y, int w, int h)
-{
- assert(con->console_type == GRAPHIC_CONSOLE);
- dpy_gfx_copy(con, src_x, src_y, dst_x, dst_y, w, h);
-}
-
DisplaySurface *qemu_console_surface(QemuConsole *console)
{
return console->surface;
int val;
ChardevVC *vc;
+ backend->type = CHARDEV_BACKEND_KIND_VC;
vc = backend->u.vc.data = g_new0(ChardevVC, 1);
qemu_chr_parse_common(opts, qapi_ChardevVC_base(vc));
{
ChardevClass *cc = CHARDEV_CLASS(oc);
+ cc->parse = qemu_chr_parse_vc;
cc->open = vc_chr_open;
cc->chr_write = vc_chr_write;
cc->chr_set_echo = vc_chr_set_echo;
/* set the default vc driver */
if (!object_class_by_name(TYPE_CHARDEV_VC)) {
type_register(&char_vc_type_info);
- register_char_driver(&vc_driver);
}
}
-static const CharDriver vc_driver = {
- .kind = CHARDEV_BACKEND_KIND_VC,
- .parse = qemu_chr_parse_vc,
-};
-
static void register_types(void)
{
type_register_static(&qemu_console_info);