qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

ui/console: ensure graphic updates don't race with TCG vCPUs

Commit 8d04fb55..

tcg: drop global lock during TCG code execution

..broke the assumption that updates to the GUI couldn't happen at the
same time as TCG vCPUs where running. As a result the TCG vCPU could
still be updating a directly mapped frame-buffer while the display
side was updating. This would cause artefacts to appear when the
update code assumed that memory block hadn't changed.

The simplest solution is to ensure the two things can't happen at the
same time like the old BQL locking scheme. Here we use the solution
introduced for MTTCG and schedule the update as async_safe_work when
we know no vCPUs can be running.

Reported-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Message-id: 20170315144825.3108-1-alex.bennee@linaro.org
Cc: BALATON Zoltan <balaton@eik.bme.hu>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

[ kraxel: updated comment clarifying the display adapters are buggy
and this is a temporary workaround ]

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>

authored by

Alex Bennée and committed by
Gerd Hoffmann
8bb93c6f 272d7dee

+20 -1
+20 -1
ui/console.c
··· 1575 1575 return true; 1576 1576 } 1577 1577 1578 + /* 1579 + * Safe DPY refresh for TCG guests. This runs when the TCG vCPUs are 1580 + * quiescent so we can avoid races between dirty page tracking for 1581 + * direct frame-buffer access by the guest. 1582 + * 1583 + * This is a temporary stopgap until we've fixed the dirty tracking 1584 + * races in display adapters. 1585 + */ 1586 + static void do_safe_dpy_refresh(CPUState *cpu, run_on_cpu_data opaque) 1587 + { 1588 + DisplayChangeListener *dcl = opaque.host_ptr; 1589 + dcl->ops->dpy_refresh(dcl); 1590 + } 1591 + 1578 1592 static void dpy_refresh(DisplayState *s) 1579 1593 { 1580 1594 DisplayChangeListener *dcl; 1581 1595 1582 1596 QLIST_FOREACH(dcl, &s->listeners, next) { 1583 1597 if (dcl->ops->dpy_refresh) { 1584 - dcl->ops->dpy_refresh(dcl); 1598 + if (tcg_enabled()) { 1599 + async_safe_run_on_cpu(first_cpu, do_safe_dpy_refresh, 1600 + RUN_ON_CPU_HOST_PTR(dcl)); 1601 + } else { 1602 + dcl->ops->dpy_refresh(dcl); 1603 + } 1585 1604 } 1586 1605 } 1587 1606 }