aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.target2
-rw-r--r--arch_init.c2
-rw-r--r--block-migration.c58
-rw-r--r--default-configs/pci.mak1
-rw-r--r--default-configs/s390x-softmmu.mak1
-rw-r--r--error.c13
-rw-r--r--error.h5
-rw-r--r--exec.c18
-rw-r--r--hmp-commands.hx3
-rw-r--r--hmp.c74
-rw-r--r--hmp.h1
-rw-r--r--hw/pci.c1
-rw-r--r--hw/qxl-render.c13
-rw-r--r--hw/qxl.c176
-rw-r--r--hw/scsi-bus.c18
-rw-r--r--hw/scsi-disk.c49
-rw-r--r--hw/virtio-scsi.c2
-rw-r--r--migration-fd.c2
-rw-r--r--migration.c74
-rw-r--r--migration.h5
-rw-r--r--monitor.c5
-rw-r--r--pc-bios/bios.binbin131072 -> 131072 bytes
-rw-r--r--qapi-schema.json21
-rw-r--r--qerror.c8
-rw-r--r--qerror.h6
-rw-r--r--qmp-commands.hx9
-rw-r--r--roms/Makefile10
-rw-r--r--roms/config.seabios1
-rwxr-xr-xroms/configure-seabios.sh5
m---------roms/seabios0
-rw-r--r--savevm.c42
-rw-r--r--sysemu.h11
-rw-r--r--trace-events66
-rw-r--r--ui/spice-core.c15
-rw-r--r--ui/spice-display.c14
-rw-r--r--vl.c5
-rw-r--r--vmstate.h3
37 files changed, 473 insertions, 266 deletions
diff --git a/Makefile.target b/Makefile.target
index 37fb7ed..63cf769 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -209,7 +209,7 @@ obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o ioport.o
# need to fix this properly
obj-$(CONFIG_NO_PCI) += pci-stub.o
obj-$(CONFIG_VIRTIO) += virtio.o virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
-obj-$(CONFIG_VIRTIO_SCSI) += virtio-scsi.o
+obj-$(CONFIG_VIRTIO) += virtio-scsi.o
obj-y += vhost_net.o
obj-$(CONFIG_VHOST_NET) += vhost.o
obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o
diff --git a/arch_init.c b/arch_init.c
index a95ef49..595badf 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -260,7 +260,7 @@ static void sort_ram_list(void)
g_free(blocks);
}
-int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
+int ram_save_live(QEMUFile *f, int stage, void *opaque)
{
ram_addr_t addr;
uint64_t bytes_transferred_last;
diff --git a/block-migration.c b/block-migration.c
index 4467468..fd2ffff 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -18,7 +18,6 @@
#include "hw/hw.h"
#include "qemu-queue.h"
#include "qemu-timer.h"
-#include "monitor.h"
#include "block-migration.h"
#include "migration.h"
#include "blockdev.h"
@@ -204,8 +203,7 @@ static void blk_mig_read_cb(void *opaque, int ret)
assert(block_mig_state.submitted >= 0);
}
-static int mig_save_device_bulk(Monitor *mon, QEMUFile *f,
- BlkMigDevState *bmds)
+static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
{
int64_t total_sectors = bmds->total_sectors;
int64_t cur_sector = bmds->cur_sector;
@@ -272,7 +270,6 @@ static void set_dirty_tracking(int enable)
static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
{
- Monitor *mon = opaque;
BlkMigDevState *bmds;
int64_t sectors;
@@ -295,19 +292,17 @@ static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
block_mig_state.total_sector_sum += sectors;
if (bmds->shared_base) {
- monitor_printf(mon, "Start migration for %s with shared base "
- "image\n",
- bs->device_name);
+ DPRINTF("Start migration for %s with shared base image\n",
+ bs->device_name);
} else {
- monitor_printf(mon, "Start full migration for %s\n",
- bs->device_name);
+ DPRINTF("Start full migration for %s\n", bs->device_name);
}
QSIMPLEQ_INSERT_TAIL(&block_mig_state.bmds_list, bmds, entry);
}
}
-static void init_blk_migration(Monitor *mon, QEMUFile *f)
+static void init_blk_migration(QEMUFile *f)
{
block_mig_state.submitted = 0;
block_mig_state.read_done = 0;
@@ -318,10 +313,10 @@ static void init_blk_migration(Monitor *mon, QEMUFile *f)
block_mig_state.total_time = 0;
block_mig_state.reads = 0;
- bdrv_iterate(init_blk_migration_it, mon);
+ bdrv_iterate(init_blk_migration_it, NULL);
}
-static int blk_mig_save_bulked_block(Monitor *mon, QEMUFile *f)
+static int blk_mig_save_bulked_block(QEMUFile *f)
{
int64_t completed_sector_sum = 0;
BlkMigDevState *bmds;
@@ -330,7 +325,7 @@ static int blk_mig_save_bulked_block(Monitor *mon, QEMUFile *f)
QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
if (bmds->bulk_completed == 0) {
- if (mig_save_device_bulk(mon, f, bmds) == 1) {
+ if (mig_save_device_bulk(f, bmds) == 1) {
/* completed bulk section for this device */
bmds->bulk_completed = 1;
}
@@ -352,8 +347,7 @@ static int blk_mig_save_bulked_block(Monitor *mon, QEMUFile *f)
block_mig_state.prev_progress = progress;
qemu_put_be64(f, (progress << BDRV_SECTOR_BITS)
| BLK_MIG_FLAG_PROGRESS);
- monitor_printf(mon, "Completed %d %%\r", progress);
- monitor_flush(mon);
+ DPRINTF("Completed %d %%\r", progress);
}
return ret;
@@ -368,8 +362,8 @@ static void blk_mig_reset_dirty_cursor(void)
}
}
-static int mig_save_device_dirty(Monitor *mon, QEMUFile *f,
- BlkMigDevState *bmds, int is_async)
+static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
+ int is_async)
{
BlkMigBlock *blk;
int64_t total_sectors = bmds->total_sectors;
@@ -428,20 +422,20 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f,
return (bmds->cur_dirty >= bmds->total_sectors);
error:
- monitor_printf(mon, "Error reading sector %" PRId64 "\n", sector);
+ DPRINTF("Error reading sector %" PRId64 "\n", sector);
qemu_file_set_error(f, ret);
g_free(blk->buf);
g_free(blk);
return 0;
}
-static int blk_mig_save_dirty_block(Monitor *mon, QEMUFile *f, int is_async)
+static int blk_mig_save_dirty_block(QEMUFile *f, int is_async)
{
BlkMigDevState *bmds;
int ret = 0;
QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
- if (mig_save_device_dirty(mon, f, bmds, is_async) == 0) {
+ if (mig_save_device_dirty(f, bmds, is_async) == 0) {
ret = 1;
break;
}
@@ -520,7 +514,7 @@ static int is_stage2_completed(void)
return 0;
}
-static void blk_mig_cleanup(Monitor *mon)
+static void blk_mig_cleanup(void)
{
BlkMigDevState *bmds;
BlkMigBlock *blk;
@@ -540,11 +534,9 @@ static void blk_mig_cleanup(Monitor *mon)
g_free(blk->buf);
g_free(blk);
}
-
- monitor_printf(mon, "\n");
}
-static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
+static int block_save_live(QEMUFile *f, int stage, void *opaque)
{
int ret;
@@ -552,7 +544,7 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
stage, block_mig_state.submitted, block_mig_state.transferred);
if (stage < 0) {
- blk_mig_cleanup(mon);
+ blk_mig_cleanup();
return 0;
}
@@ -563,7 +555,7 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
}
if (stage == 1) {
- init_blk_migration(mon, f);
+ init_blk_migration(f);
/* start track dirty blocks */
set_dirty_tracking(1);
@@ -573,7 +565,7 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
ret = qemu_file_get_error(f);
if (ret) {
- blk_mig_cleanup(mon);
+ blk_mig_cleanup();
return ret;
}
@@ -586,12 +578,12 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
qemu_file_get_rate_limit(f)) {
if (block_mig_state.bulk_completed == 0) {
/* first finish the bulk phase */
- if (blk_mig_save_bulked_block(mon, f) == 0) {
+ if (blk_mig_save_bulked_block(f) == 0) {
/* finished saving bulk on all devices */
block_mig_state.bulk_completed = 1;
}
} else {
- if (blk_mig_save_dirty_block(mon, f, 1) == 0) {
+ if (blk_mig_save_dirty_block(f, 1) == 0) {
/* no more dirty blocks */
break;
}
@@ -602,7 +594,7 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
ret = qemu_file_get_error(f);
if (ret) {
- blk_mig_cleanup(mon);
+ blk_mig_cleanup();
return ret;
}
}
@@ -612,8 +604,8 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
all async read completed */
assert(block_mig_state.submitted == 0);
- while (blk_mig_save_dirty_block(mon, f, 0) != 0);
- blk_mig_cleanup(mon);
+ while (blk_mig_save_dirty_block(f, 0) != 0);
+ blk_mig_cleanup();
/* report completion */
qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS);
@@ -623,7 +615,7 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
return ret;
}
- monitor_printf(mon, "Block migration completed\n");
+ DPRINTF("Block migration completed\n");
}
qemu_put_be64(f, BLK_MIG_FLAG_EOS);
diff --git a/default-configs/pci.mak b/default-configs/pci.mak
index 21e4ccf..9d3e1db 100644
--- a/default-configs/pci.mak
+++ b/default-configs/pci.mak
@@ -1,6 +1,5 @@
CONFIG_PCI=y
CONFIG_VIRTIO_PCI=y
-CONFIG_VIRTIO_SCSI=y
CONFIG_VIRTIO=y
CONFIG_USB_UHCI=y
CONFIG_USB_OHCI=y
diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak
index e588803..3005729 100644
--- a/default-configs/s390x-softmmu.mak
+++ b/default-configs/s390x-softmmu.mak
@@ -1,2 +1 @@
CONFIG_VIRTIO=y
-CONFIG_VIRTIO_SCSI=y
diff --git a/error.c b/error.c
index 990050f..d3455ab 100644
--- a/error.c
+++ b/error.c
@@ -43,6 +43,19 @@ void error_set(Error **errp, const char *fmt, ...)
*errp = err;
}
+Error *error_copy(const Error *err)
+{
+ Error *err_new;
+
+ err_new = g_malloc0(sizeof(*err));
+ err_new->msg = g_strdup(err->msg);
+ err_new->fmt = err->fmt;
+ err_new->obj = err->obj;
+ QINCREF(err_new->obj);
+
+ return err_new;
+}
+
bool error_is_set(Error **errp)
{
return (errp && *errp);
diff --git a/error.h b/error.h
index 6361f40..45ff6c1 100644
--- a/error.h
+++ b/error.h
@@ -35,6 +35,11 @@ void error_set(Error **err, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
bool error_is_set(Error **err);
/**
+ * Returns an exact copy of the error passed as an argument.
+ */
+Error *error_copy(const Error *err);
+
+/**
* Get a human readable representation of an error object.
*/
const char *error_get_pretty(Error *err);
diff --git a/exec.c b/exec.c
index be392e2..265e895 100644
--- a/exec.c
+++ b/exec.c
@@ -2031,14 +2031,19 @@ static void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr,
cpu_physical_memory_set_dirty_flags(ram_addr, CODE_DIRTY_FLAG);
}
+static bool tlb_is_dirty_ram(CPUTLBEntry *tlbe)
+{
+ return (tlbe->addr_write & (TLB_INVALID_MASK|TLB_MMIO|TLB_NOTDIRTY)) == 0;
+}
+
static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
unsigned long start, unsigned long length)
{
unsigned long addr;
- if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr) {
+ if (tlb_is_dirty_ram(tlb_entry)) {
addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
if ((addr - start) < length) {
- tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | TLB_NOTDIRTY;
+ tlb_entry->addr_write |= TLB_NOTDIRTY;
}
}
}
@@ -2091,7 +2096,7 @@ static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
ram_addr_t ram_addr;
void *p;
- if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr) {
+ if (tlb_is_dirty_ram(tlb_entry)) {
p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
+ tlb_entry->addend);
ram_addr = qemu_ram_addr_from_host_nofail(p);
@@ -3851,8 +3856,8 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
}
} else {
/* RAM case */
- ptr = qemu_get_ram_ptr(section->mr->ram_addr)
- + section_addr(section, addr);
+ ptr = qemu_get_ram_ptr(section->mr->ram_addr
+ + section_addr(section, addr));
memcpy(buf, ptr, l);
qemu_put_ram_ptr(ptr);
}
@@ -4604,7 +4609,8 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
pd = env1->iotlb[mmu_idx][page_index] & ~TARGET_PAGE_MASK;
mr = iotlb_to_region(pd);
if (mr != &io_mem_ram && mr != &io_mem_rom
- && mr != &io_mem_notdirty && !mr->rom_device) {
+ && mr != &io_mem_notdirty && !mr->rom_device
+ && mr != &io_mem_watch) {
#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC)
cpu_unassigned_access(env1, addr, 0, 1, 0, 4);
#else
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 6980214..bd35a3e 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -806,8 +806,7 @@ ETEXI
" full copy of disk\n\t\t\t -i for migration without "
"shared storage with incremental copy of disk "
"(base image shared between src and destination)",
- .user_print = monitor_user_noop,
- .mhandler.cmd_new = do_migrate,
+ .mhandler.cmd = hmp_migrate,
},
diff --git a/hmp.c b/hmp.c
index 290c43d..9cf2d13 100644
--- a/hmp.c
+++ b/hmp.c
@@ -14,6 +14,7 @@
*/
#include "hmp.h"
+#include "qemu-timer.h"
#include "qmp-commands.h"
static void hmp_handle_error(Monitor *mon, Error **errp)
@@ -860,3 +861,76 @@ void hmp_block_job_cancel(Monitor *mon, const QDict *qdict)
hmp_handle_error(mon, &error);
}
+
+typedef struct MigrationStatus
+{
+ QEMUTimer *timer;
+ Monitor *mon;
+ bool is_block_migration;
+} MigrationStatus;
+
+static void hmp_migrate_status_cb(void *opaque)
+{
+ MigrationStatus *status = opaque;
+ MigrationInfo *info;
+
+ info = qmp_query_migrate(NULL);
+ if (!info->has_status || strcmp(info->status, "active") == 0) {
+ if (info->has_disk) {
+ int progress;
+
+ if (info->disk->remaining) {
+ progress = info->disk->transferred * 100 / info->disk->total;
+ } else {
+ progress = 100;
+ }
+
+ monitor_printf(status->mon, "Completed %d %%\r", progress);
+ monitor_flush(status->mon);
+ }
+
+ qemu_mod_timer(status->timer, qemu_get_clock_ms(rt_clock) + 1000);
+ } else {
+ if (status->is_block_migration) {
+ monitor_printf(status->mon, "\n");
+ }
+ monitor_resume(status->mon);
+ qemu_del_timer(status->timer);
+ g_free(status);
+ }
+
+ qapi_free_MigrationInfo(info);
+}
+
+void hmp_migrate(Monitor *mon, const QDict *qdict)
+{
+ int detach = qdict_get_try_bool(qdict, "detach", 0);
+ int blk = qdict_get_try_bool(qdict, "blk", 0);
+ int inc = qdict_get_try_bool(qdict, "inc", 0);
+ const char *uri = qdict_get_str(qdict, "uri");
+ Error *err = NULL;
+
+ qmp_migrate(uri, !!blk, blk, !!inc, inc, false, false, &err);
+ if (err) {
+ monitor_printf(mon, "migrate: %s\n", error_get_pretty(err));
+ error_free(err);
+ return;
+ }
+
+ if (!detach) {
+ MigrationStatus *status;
+
+ if (monitor_suspend(mon) < 0) {
+ monitor_printf(mon, "terminal does not allow synchronous "
+ "migration, continuing detached\n");
+ return;
+ }
+
+ status = g_malloc0(sizeof(*status));
+ status->mon = mon;
+ status->is_block_migration = blk || inc;
+ status->timer = qemu_new_timer_ms(rt_clock, hmp_migrate_status_cb,
+ status);
+ qemu_mod_timer(status->timer, qemu_get_clock_ms(rt_clock));
+ }
+}
diff --git a/hmp.h b/hmp.h
index 5409464..8807853 100644
--- a/hmp.h
+++ b/hmp.h
@@ -59,5 +59,6 @@ void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict);
void hmp_block_stream(Monitor *mon, const QDict *qdict);
void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict);
void hmp_block_job_cancel(Monitor *mon, const QDict *qdict);
+void hmp_migrate(Monitor *mon, const QDict *qdict);
#endif
diff --git a/hw/pci.c b/hw/pci.c
index bf046bf..ed8ec99 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -841,7 +841,6 @@ static int pci_unregister_device(DeviceState *dev)
pci_unregister_io_regions(pci_dev);
pci_del_option_rom(pci_dev);
- g_free(pci_dev->romfile);
do_pci_unregister_device(pci_dev);
return 0;
}
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index 25857f6..28ab182 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -31,11 +31,10 @@ static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect)
return;
}
if (!qxl->guest_primary.data) {
- dprint(qxl, 1, "%s: initializing guest_primary.data\n", __func__);
+ trace_qxl_render_blit_guest_primary_initialized();
qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
}
- dprint(qxl, 2, "%s: stride %d, [%d, %d, %d, %d]\n", __func__,
- qxl->guest_primary.qxl_stride,
+ trace_qxl_render_blit(qxl->guest_primary.qxl_stride,
rect->left, rect->right, rect->top, rect->bottom);
src = qxl->guest_primary.data;
if (qxl->guest_primary.qxl_stride < 0) {
@@ -107,8 +106,7 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
qxl_set_rect_to_surface(qxl, &qxl->dirty[0]);
qxl->num_dirty_rects = 1;
- dprint(qxl, 1, "%s: %dx%d, stride %d, bpp %d, depth %d\n",
- __FUNCTION__,
+ trace_qxl_render_guest_primary_resized(
qxl->guest_primary.surface.width,
qxl->guest_primary.surface.height,
qxl->guest_primary.qxl_stride,
@@ -118,8 +116,6 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
if (surface->width != qxl->guest_primary.surface.width ||
surface->height != qxl->guest_primary.surface.height) {
if (qxl->guest_primary.qxl_stride > 0) {
- dprint(qxl, 1, "%s: using guest_primary for displaysurface\n",
- __func__);
qemu_free_displaysurface(vga->ds);
qemu_create_displaysurface_from(qxl->guest_primary.surface.width,
qxl->guest_primary.surface.height,
@@ -127,8 +123,6 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
qxl->guest_primary.abs_stride,
qxl->guest_primary.data);
} else {
- dprint(qxl, 1, "%s: resizing displaysurface to guest_primary\n",
- __func__);
qemu_resize_displaysurface(vga->ds,
qxl->guest_primary.surface.width,
qxl->guest_primary.surface.height);
@@ -187,6 +181,7 @@ void qxl_render_update_area_bh(void *opaque)
void qxl_render_update_area_done(PCIQXLDevice *qxl, QXLCookie *cookie)
{
qemu_mutex_lock(&qxl->ssd.lock);
+ trace_qxl_render_update_area_done(cookie);
qemu_bh_schedule(qxl->update_area_bh);
qxl->render_update_cookie_num--;
qemu_mutex_unlock(&qxl->ssd.lock);
diff --git a/hw/qxl.c b/hw/qxl.c
index e17b0e3..47a162e 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -23,6 +23,7 @@
#include "qemu-queue.h"
#include "monitor.h"
#include "sysemu.h"
+#include "trace.h"
#include "qxl.h"
@@ -143,19 +144,24 @@ void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
uint32_t clear_dirty_region,
qxl_async_io async, struct QXLCookie *cookie)
{
+ trace_qxl_spice_update_area(qxl->id, surface_id, area->left, area->right,
+ area->top, area->bottom);
+ trace_qxl_spice_update_area_rest(qxl->id, num_dirty_rects,
+ clear_dirty_region);
if (async == QXL_SYNC) {
qxl->ssd.worker->update_area(qxl->ssd.worker, surface_id, area,
dirty_rects, num_dirty_rects, clear_dirty_region);
} else {
assert(cookie != NULL);
spice_qxl_update_area_async(&qxl->ssd.qxl, surface_id, area,
- clear_dirty_region, (uint64_t)cookie);
+ clear_dirty_region, (uintptr_t)cookie);
}
}
static void qxl_spice_destroy_surface_wait_complete(PCIQXLDevice *qxl,
uint32_t id)
{
+ trace_qxl_spice_destroy_surface_wait_complete(qxl->id, id);
qemu_mutex_lock(&qxl->track_lock);
qxl->guest_surfaces.cmds[id] = 0;
qxl->guest_surfaces.count--;
@@ -167,42 +173,48 @@ static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id,
{
QXLCookie *cookie;
+ trace_qxl_spice_destroy_surface_wait(qxl->id, id, async);
if (async) {
cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO,
QXL_IO_DESTROY_SURFACE_ASYNC);
cookie->u.surface_id = id;
- spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id, (uint64_t)cookie);
+ spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id, (uintptr_t)cookie);
} else {
qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id);
- qxl_spice_destroy_surface_wait_complete(qxl, id);
}
}
static void qxl_spice_flush_surfaces_async(PCIQXLDevice *qxl)
{
+ trace_qxl_spice_flush_surfaces_async(qxl->id, qxl->guest_surfaces.count,
+ qxl->num_free_res);
spice_qxl_flush_surfaces_async(&qxl->ssd.qxl,
- (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
- QXL_IO_FLUSH_SURFACES_ASYNC));
+ (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+ QXL_IO_FLUSH_SURFACES_ASYNC));
}
void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
uint32_t count)
{
+ trace_qxl_spice_loadvm_commands(qxl->id, ext, count);
qxl->ssd.worker->loadvm_commands(qxl->ssd.worker, ext, count);
}
void qxl_spice_oom(PCIQXLDevice *qxl)
{
+ trace_qxl_spice_oom(qxl->id);
qxl->ssd.worker->oom(qxl->ssd.worker);
}
void qxl_spice_reset_memslots(PCIQXLDevice *qxl)
{
+ trace_qxl_spice_reset_memslots(qxl->id);
qxl->ssd.worker->reset_memslots(qxl->ssd.worker);
}
static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl)
{
+ trace_qxl_spice_destroy_surfaces_complete(qxl->id);
qemu_mutex_lock(&qxl->track_lock);
memset(&qxl->guest_surfaces.cmds, 0, sizeof(qxl->guest_surfaces.cmds));
qxl->guest_surfaces.count = 0;
@@ -211,10 +223,11 @@ static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl)
static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async)
{
+ trace_qxl_spice_destroy_surfaces(qxl->id, async);
if (async) {
spice_qxl_destroy_surfaces_async(&qxl->ssd.qxl,
- (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
- QXL_IO_DESTROY_ALL_SURFACES_ASYNC));
+ (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+ QXL_IO_DESTROY_ALL_SURFACES_ASYNC));
} else {
qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker);
qxl_spice_destroy_surfaces_complete(qxl);
@@ -223,11 +236,13 @@ static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async)
void qxl_spice_reset_image_cache(PCIQXLDevice *qxl)
{
+ trace_qxl_spice_reset_image_cache(qxl->id);
qxl->ssd.worker->reset_image_cache(qxl->ssd.worker);
}
void qxl_spice_reset_cursor(PCIQXLDevice *qxl)
{
+ trace_qxl_spice_reset_cursor(qxl->id);
qxl->ssd.worker->reset_cursor(qxl->ssd.worker);
qemu_mutex_lock(&qxl->track_lock);
qxl->guest_cursor = 0;
@@ -409,7 +424,7 @@ static void interface_attach_worker(QXLInstance *sin, QXLWorker *qxl_worker)
{
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
- dprint(qxl, 1, "%s:\n", __FUNCTION__);
+ trace_qxl_interface_attach_worker(qxl->id);
qxl->ssd.worker = qxl_worker;
}
@@ -417,7 +432,7 @@ static void interface_set_compression_level(QXLInstance *sin, int level)
{
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
- dprint(qxl, 1, "%s: %d\n", __FUNCTION__, level);
+ trace_qxl_interface_set_compression_level(qxl->id, level);
qxl->shadow_rom.compression_level = cpu_to_le32(level);
qxl->rom->compression_level = cpu_to_le32(level);
qxl_rom_set_dirty(qxl);
@@ -427,6 +442,7 @@ static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time)
{
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
+ trace_qxl_interface_set_mm_time(qxl->id, mm_time);
qxl->shadow_rom.mm_clock = cpu_to_le32(mm_time);
qxl->rom->mm_clock = cpu_to_le32(mm_time);
qxl_rom_set_dirty(qxl);
@@ -436,7 +452,7 @@ static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
{
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
- dprint(qxl, 1, "%s:\n", __FUNCTION__);
+ trace_qxl_interface_get_init_info(qxl->id);
info->memslot_gen_bits = MEMSLOT_GENERATION_BITS;
info->memslot_id_bits = MEMSLOT_SLOT_BITS;
info->num_memslots = NUM_MEMSLOTS;
@@ -505,9 +521,10 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
QXLCommand *cmd;
int notify, ret;
+ trace_qxl_ring_command_check(qxl->id, qxl_mode_to_string(qxl->mode));
+
switch (qxl->mode) {
case QXL_MODE_VGA:
- dprint(qxl, 2, "%s: vga\n", __FUNCTION__);
ret = false;
qemu_mutex_lock(&qxl->ssd.lock);
if (qxl->ssd.update != NULL) {
@@ -518,19 +535,18 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
}
qemu_mutex_unlock(&qxl->ssd.lock);
if (ret) {
- dprint(qxl, 2, "%s %s\n", __FUNCTION__, qxl_mode_to_string(qxl->mode));
+ trace_qxl_ring_command_get(qxl->id, qxl_mode_to_string(qxl->mode));
qxl_log_command(qxl, "vga", ext);
}
return ret;
case QXL_MODE_COMPAT:
case QXL_MODE_NATIVE:
case QXL_MODE_UNDEFINED:
- dprint(qxl, 4, "%s: %s\n", __FUNCTION__, qxl_mode_to_string(qxl->mode));
ring = &qxl->ram->cmd_ring;
if (SPICE_RING_IS_EMPTY(ring)) {
return false;
}
- dprint(qxl, 2, "%s: %s\n", __FUNCTION__, qxl_mode_to_string(qxl->mode));
+ trace_qxl_ring_command_get(qxl->id, qxl_mode_to_string(qxl->mode));
SPICE_RING_CONS_ITEM(ring, cmd);
ext->cmd = *cmd;
ext->group_id = MEMSLOT_GROUP_GUEST;
@@ -555,6 +571,7 @@ static int interface_req_cmd_notification(QXLInstance *sin)
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
int wait = 1;
+ trace_qxl_ring_command_req_notification(qxl->id);
switch (qxl->mode) {
case QXL_MODE_COMPAT:
case QXL_MODE_NATIVE:
@@ -592,10 +609,11 @@ static inline void qxl_push_free_res(PCIQXLDevice *d, int flush)
}
SPICE_RING_PUSH(ring, notify);
- dprint(d, 2, "free: push %d items, notify %s, ring %d/%d [%d,%d]\n",
- d->num_free_res, notify ? "yes" : "no",
- ring->prod - ring->cons, ring->num_items,
- ring->prod, ring->cons);
+ trace_qxl_ring_res_push(d->id, qxl_mode_to_string(d->mode),
+ d->guest_surfaces.count, d->num_free_res,
+ d->last_release, notify ? "yes" : "no");
+ trace_qxl_ring_res_push_rest(d->id, ring->prod - ring->cons,
+ ring->num_items, ring->prod, ring->cons);
if (notify) {
qxl_send_events(d, QXL_INTERRUPT_DISPLAY);
}
@@ -642,7 +660,7 @@ static void interface_release_resource(QXLInstance *sin,
}
qxl->last_release = ext.info;
qxl->num_free_res++;
- dprint(qxl, 3, "%4d\r", qxl->num_free_res);
+ trace_qxl_ring_res_put(qxl->id, qxl->num_free_res);
qxl_push_free_res(qxl, 0);
}
@@ -654,6 +672,8 @@ static int interface_get_cursor_command(QXLInstance *sin, struct QXLCommandExt *
QXLCommand *cmd;
int notify;
+ trace_qxl_ring_cursor_check(qxl->id, qxl_mode_to_string(qxl->mode));
+
switch (qxl->mode) {
case QXL_MODE_COMPAT:
case QXL_MODE_NATIVE:
@@ -677,6 +697,7 @@ static int interface_get_cursor_command(QXLInstance *sin, struct QXLCommandExt *
if (qxl->id == 0) {
qxl_render_cursor(qxl, ext);
}
+ trace_qxl_ring_cursor_get(qxl->id, qxl_mode_to_string(qxl->mode));
return true;
default:
return false;
@@ -689,6 +710,7 @@ static int interface_req_cursor_notification(QXLInstance *sin)
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
int wait = 1;
+ trace_qxl_ring_cursor_req_notification(qxl->id);
switch (qxl->mode) {
case QXL_MODE_COMPAT:
case QXL_MODE_NATIVE:
@@ -716,7 +738,6 @@ static int interface_flush_resources(QXLInstance *sin)
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
int ret;
- dprint(qxl, 1, "free: guest flush (have %d)\n", qxl->num_free_res);
ret = qxl->num_free_res;
if (ret) {
qxl_push_free_res(qxl, 1);
@@ -736,14 +757,14 @@ static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie)
qxl->current_async = QXL_UNDEFINED_IO;
qemu_mutex_unlock(&qxl->async_lock);
- dprint(qxl, 2, "async_complete: %d (%p) done\n", current_async, cookie);
+ trace_qxl_interface_async_complete_io(qxl->id, current_async, cookie);
if (!cookie) {
fprintf(stderr, "qxl: %s: error, cookie is NULL\n", __func__);
return;
}
if (cookie && current_async != cookie->io) {
fprintf(stderr,
- "qxl: %s: error: current_async = %d != %ld = cookie->io\n",
+ "qxl: %s: error: current_async = %d != %" PRId64 " = cookie->io\n",
__func__, current_async, cookie->io);
}
switch (current_async) {
@@ -782,11 +803,15 @@ static void interface_update_area_complete(QXLInstance *sin,
qemu_mutex_unlock(&qxl->ssd.lock);
return;
}
+ trace_qxl_interface_update_area_complete(qxl->id, surface_id, dirty->left,
+ dirty->right, dirty->top, dirty->bottom);
+ trace_qxl_interface_update_area_complete_rest(qxl->id, num_updated_rects);
if (qxl->num_dirty_rects + num_updated_rects > QXL_NUM_DIRTY_RECTS) {
/*
* overflow - treat this as a full update. Not expected to be common.
*/
- dprint(qxl, 1, "%s: overflow of dirty rects\n", __func__);
+ trace_qxl_interface_update_area_complete_overflow(qxl->id,
+ QXL_NUM_DIRTY_RECTS);
qxl->guest_primary.resized = 1;
}
if (qxl->guest_primary.resized) {
@@ -802,8 +827,8 @@ static void interface_update_area_complete(QXLInstance *sin,
qxl->dirty[qxl_i++] = dirty[i];
}
qxl->num_dirty_rects += num_updated_rects;
- dprint(qxl, 1, "%s: scheduling update_area_bh, #dirty %d\n",
- __func__, qxl->num_dirty_rects);
+ trace_qxl_interface_update_area_complete_schedule_bh(qxl->id,
+ qxl->num_dirty_rects);
qemu_bh_schedule(qxl->update_area_bh);
qemu_mutex_unlock(&qxl->ssd.lock);
}
@@ -812,7 +837,7 @@ static void interface_update_area_complete(QXLInstance *sin,
static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token)
{
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
- QXLCookie *cookie = (QXLCookie *)cookie_token;
+ QXLCookie *cookie = (QXLCookie *)(uintptr_t)cookie_token;
switch (cookie->type) {
case QXL_COOKIE_TYPE_IO:
@@ -857,7 +882,7 @@ static void qxl_enter_vga_mode(PCIQXLDevice *d)
if (d->mode == QXL_MODE_VGA) {
return;
}
- dprint(d, 1, "%s\n", __FUNCTION__);
+ trace_qxl_enter_vga_mode(d->id);
qemu_spice_create_host_primary(&d->ssd);
d->mode = QXL_MODE_VGA;
memset(&d->ssd.dirty, 0, sizeof(d->ssd.dirty));
@@ -868,7 +893,7 @@ static void qxl_exit_vga_mode(PCIQXLDevice *d)
if (d->mode != QXL_MODE_VGA) {
return;
}
- dprint(d, 1, "%s\n", __FUNCTION__);
+ trace_qxl_exit_vga_mode(d->id);
qxl_destroy_primary(d, QXL_SYNC);
}
@@ -905,7 +930,7 @@ static void qxl_reset_state(PCIQXLDevice *d)
static void qxl_soft_reset(PCIQXLDevice *d)
{
- dprint(d, 1, "%s:\n", __FUNCTION__);
+ trace_qxl_soft_reset(d->id);
qxl_check_state(d);
if (d->id == 0) {
@@ -917,8 +942,7 @@ static void qxl_soft_reset(PCIQXLDevice *d)
static void qxl_hard_reset(PCIQXLDevice *d, int loadvm)
{
- dprint(d, 1, "%s: start%s\n", __FUNCTION__,
- loadvm ? " (loadvm)" : "");
+ trace_qxl_hard_reset(d->id, loadvm);
qxl_spice_reset_cursor(d);
qxl_spice_reset_image_cache(d);
@@ -933,13 +957,12 @@ static void qxl_hard_reset(PCIQXLDevice *d, int loadvm)
}
qemu_spice_create_host_memslot(&d->ssd);
qxl_soft_reset(d);
-
- dprint(d, 1, "%s: done\n", __FUNCTION__);
}
static void qxl_reset_handler(DeviceState *dev)
{
PCIQXLDevice *d = DO_UPCAST(PCIQXLDevice, pci.qdev, dev);
+
qxl_hard_reset(d, 0);
}
@@ -948,8 +971,8 @@ static void qxl_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
VGACommonState *vga = opaque;
PCIQXLDevice *qxl = container_of(vga, PCIQXLDevice, vga);
+ trace_qxl_io_write_vga(qxl->id, qxl_mode_to_string(qxl->mode), addr, val);
if (qxl->mode != QXL_MODE_VGA) {
- dprint(qxl, 1, "%s\n", __FUNCTION__);
qxl_destroy_primary(qxl, QXL_SYNC);
qxl_soft_reset(qxl);
}
@@ -990,9 +1013,7 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
guest_start = le64_to_cpu(d->guest_slots[slot_id].slot.mem_start);
guest_end = le64_to_cpu(d->guest_slots[slot_id].slot.mem_end);
- dprint(d, 1, "%s: slot %d: guest phys 0x%" PRIx64 " - 0x%" PRIx64 "\n",
- __FUNCTION__, slot_id,
- guest_start, guest_end);
+ trace_qxl_memslot_add_guest(d->id, slot_id, guest_start, guest_end);
PANIC_ON(slot_id >= NUM_MEMSLOTS);
PANIC_ON(guest_start > guest_end);
@@ -1039,10 +1060,6 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
memslot.generation = d->rom->slot_generation = 0;
qxl_rom_set_dirty(d);
- dprint(d, 1, "%s: slot %d: host virt 0x%lx - 0x%lx\n",
- __FUNCTION__, memslot.slot_id,
- memslot.virt_start, memslot.virt_end);
-
qemu_spice_add_memslot(&d->ssd, &memslot, async);
d->guest_slots[slot_id].ptr = (void*)memslot.virt_start;
d->guest_slots[slot_id].size = memslot.virt_end - memslot.virt_start;
@@ -1052,21 +1069,19 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
static void qxl_del_memslot(PCIQXLDevice *d, uint32_t slot_id)
{
- dprint(d, 1, "%s: slot %d\n", __FUNCTION__, slot_id);
qemu_spice_del_memslot(&d->ssd, MEMSLOT_GROUP_HOST, slot_id);
d->guest_slots[slot_id].active = 0;
}
static void qxl_reset_memslots(PCIQXLDevice *d)
{
- dprint(d, 1, "%s:\n", __FUNCTION__);
qxl_spice_reset_memslots(d);
memset(&d->guest_slots, 0, sizeof(d->guest_slots));
}
static void qxl_reset_surfaces(PCIQXLDevice *d)
{
- dprint(d, 1, "%s:\n", __FUNCTION__);
+ trace_qxl_reset_surfaces(d->id);
d->mode = QXL_MODE_UNDEFINED;
qxl_spice_destroy_surfaces(d, QXL_SYNC);
}
@@ -1108,9 +1123,6 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm,
assert(qxl->mode != QXL_MODE_NATIVE);
qxl_exit_vga_mode(qxl);
- dprint(qxl, 1, "%s: %dx%d\n", __FUNCTION__,
- le32_to_cpu(sc->width), le32_to_cpu(sc->height));
-
surface.format = le32_to_cpu(sc->format);
surface.height = le32_to_cpu(sc->height);
surface.mem = le64_to_cpu(sc->mem);
@@ -1119,6 +1131,10 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm,
surface.width = le32_to_cpu(sc->width);
surface.type = le32_to_cpu(sc->type);
surface.flags = le32_to_cpu(sc->flags);
+ trace_qxl_create_guest_primary(qxl->id, sc->width, sc->height, sc->mem,
+ sc->format, sc->position);
+ trace_qxl_create_guest_primary_rest(qxl->id, sc->stride, sc->type,
+ sc->flags);
surface.mouse_mode = true;
surface.group_id = MEMSLOT_GROUP_GUEST;
@@ -1142,7 +1158,7 @@ static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async)
if (d->mode == QXL_MODE_UNDEFINED) {
return 0;
}
- dprint(d, 1, "%s\n", __FUNCTION__);
+ trace_qxl_destroy_primary(d->id);
d->mode = QXL_MODE_UNDEFINED;
qemu_spice_destroy_primary_surface(&d->ssd, 0, async);
qxl_spice_reset_cursor(d);
@@ -1169,8 +1185,8 @@ static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm)
.mem = devmem + d->shadow_rom.draw_area_offset,
};
- dprint(d, 1, "%s: mode %d [ %d x %d @ %d bpp devmem 0x%" PRIx64 " ]\n",
- __func__, modenr, mode->x_res, mode->y_res, mode->bits, devmem);
+ trace_qxl_set_mode(d->id, modenr, mode->x_res, mode->y_res, mode->bits,
+ devmem);
if (!loadvm) {
qxl_hard_reset(d, 0);
}
@@ -1216,8 +1232,8 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
if (d->mode != QXL_MODE_VGA) {
break;
}
- dprint(d, 1, "%s: unexpected port 0x%x (%s) in vga mode\n",
- __func__, io_port, io_port_to_string(io_port));
+ trace_qxl_io_unexpected_vga_mode(d->id,
+ io_port, io_port_to_string(io_port));
/* be nice to buggy guest drivers */
if (io_port >= QXL_IO_UPDATE_AREA_ASYNC &&
io_port <= QXL_IO_DESTROY_ALL_SURFACES_ASYNC) {
@@ -1259,11 +1275,12 @@ async_common:
}
d->current_async = orig_io_port;
qemu_mutex_unlock(&d->async_lock);
- dprint(d, 2, "start async %d (%"PRId64")\n", io_port, val);
break;
default:
break;
}
+ trace_qxl_io_write(d->id, qxl_mode_to_string(d->mode), addr, val, size,
+ async);
switch (io_port) {
case QXL_IO_UPDATE_AREA:
@@ -1299,7 +1316,6 @@ async_common:
d->oom_running = 0;
break;
case QXL_IO_SET_MODE:
- dprint(d, 1, "QXL_SET_MODE %d\n", (int)val);
qxl_set_mode(d, val, 0);
break;
case QXL_IO_LOG:
@@ -1309,7 +1325,6 @@ async_common:
}
break;
case QXL_IO_RESET:
- dprint(d, 1, "QXL_IO_RESET\n");
qxl_hard_reset(d, 0);
break;
case QXL_IO_MEMSLOT_ADD:
@@ -1337,7 +1352,6 @@ async_common:
async);
goto cancel_async;
}
- dprint(d, 1, "QXL_IO_CREATE_PRIMARY async=%d\n", async);
d->guest_primary.surface = d->ram->create_surface;
qxl_create_guest_primary(d, 0, async);
break;
@@ -1347,11 +1361,9 @@ async_common:
async);
goto cancel_async;
}
- dprint(d, 1, "QXL_IO_DESTROY_PRIMARY (async=%d) (%s)\n", async,
- qxl_mode_to_string(d->mode));
if (!qxl_destroy_primary(d, async)) {
- dprint(d, 1, "QXL_IO_DESTROY_PRIMARY_ASYNC in %s, ignored\n",
- qxl_mode_to_string(d->mode));
+ trace_qxl_io_destroy_primary_ignored(d->id,
+ qxl_mode_to_string(d->mode));
goto cancel_async;
}
break;
@@ -1371,16 +1383,9 @@ async_common:
ring->prod, ring->cons);
}
qxl_push_free_res(d, 1 /* flush */);
- dprint(d, 1, "QXL_IO_FLUSH_RELEASE exit (%s, s#=%d, res#=%d,%p)\n",
- qxl_mode_to_string(d->mode), d->guest_surfaces.count,
- d->num_free_res, d->last_release);
break;
}
case QXL_IO_FLUSH_SURFACES_ASYNC:
- dprint(d, 1, "QXL_IO_FLUSH_SURFACES_ASYNC"
- " (%"PRId64") (%s, s#=%d, res#=%d)\n",
- val, qxl_mode_to_string(d->mode), d->guest_surfaces.count,
- d->num_free_res);
qxl_spice_flush_surfaces_async(d);
break;
case QXL_IO_DESTROY_ALL_SURFACES:
@@ -1406,7 +1411,7 @@ static uint64_t ioport_read(void *opaque, target_phys_addr_t addr,
{
PCIQXLDevice *d = opaque;
- dprint(d, 1, "%s: unexpected\n", __FUNCTION__);
+ trace_qxl_io_read_unexpected(d->id);
return 0xff;
}
@@ -1452,16 +1457,17 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
static void init_pipe_signaling(PCIQXLDevice *d)
{
- if (pipe(d->pipe) < 0) {
- dprint(d, 1, "%s: pipe creation failed\n", __FUNCTION__);
- return;
- }
- fcntl(d->pipe[0], F_SETFL, O_NONBLOCK);
- fcntl(d->pipe[1], F_SETFL, O_NONBLOCK);
- fcntl(d->pipe[0], F_SETOWN, getpid());
+ if (pipe(d->pipe) < 0) {
+ fprintf(stderr, "%s:%s: qxl pipe creation failed\n",
+ __FILE__, __func__);
+ exit(1);
+ }
+ fcntl(d->pipe[0], F_SETFL, O_NONBLOCK);
+ fcntl(d->pipe[1], F_SETFL, O_NONBLOCK);
+ fcntl(d->pipe[0], F_SETOWN, getpid());
- qemu_thread_get_self(&d->main);
- qemu_set_fd_handler(d->pipe[0], pipe_read, NULL, d);
+ qemu_thread_get_self(&d->main);
+ qemu_set_fd_handler(d->pipe[0], pipe_read, NULL, d);
}
/* graphics console */
@@ -1556,8 +1562,7 @@ static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
surface_offset -= vram_start;
surface_size = cmd->u.surface_create.height *
abs(cmd->u.surface_create.stride);
- dprint(qxl, 3, "%s: dirty surface %d, offset %d, size %d\n", __func__,
- i, (int)surface_offset, surface_size);
+ trace_qxl_surfaces_dirty(qxl->id, i, (int)surface_offset, surface_size);
qxl_set_dirty(&qxl->vram_bar, surface_offset, surface_size);
}
}
@@ -1791,7 +1796,7 @@ static void qxl_pre_save(void *opaque)
PCIQXLDevice* d = opaque;
uint8_t *ram_start = d->vga.vram_ptr;
- dprint(d, 1, "%s:\n", __FUNCTION__);
+ trace_qxl_pre_save(d->id);
if (d->last_release == NULL) {
d->last_release_offset = 0;
} else {
@@ -1804,10 +1809,9 @@ static int qxl_pre_load(void *opaque)
{
PCIQXLDevice* d = opaque;
- dprint(d, 1, "%s: start\n", __FUNCTION__);
+ trace_qxl_pre_load(d->id);
qxl_hard_reset(d, 1);
qxl_exit_vga_mode(d);
- dprint(d, 1, "%s: done\n", __FUNCTION__);
return 0;
}
@@ -1819,7 +1823,6 @@ static void qxl_create_memslots(PCIQXLDevice *d)
if (!d->guest_slots[i].active) {
continue;
}
- dprint(d, 1, "%s: restoring guest slot %d\n", __func__, i);
qxl_add_memslot(d, i, 0, QXL_SYNC);
}
}
@@ -1831,8 +1834,6 @@ static int qxl_post_load(void *opaque, int version)
QXLCommandExt *cmds;
int in, out, newmode;
- dprint(d, 1, "%s: start\n", __FUNCTION__);
-
assert(d->last_release_offset < d->vga.vram_size);
if (d->last_release_offset == 0) {
d->last_release = NULL;
@@ -1842,8 +1843,7 @@ static int qxl_post_load(void *opaque, int version)
d->modes = (QXLModes*)((uint8_t*)d->rom + d->rom->modes_offset);
- dprint(d, 1, "%s: restore mode (%s)\n", __FUNCTION__,
- qxl_mode_to_string(d->mode));
+ trace_qxl_post_load(d->id, qxl_mode_to_string(d->mode));
newmode = d->mode;
d->mode = QXL_MODE_UNDEFINED;
@@ -1885,8 +1885,6 @@ static int qxl_post_load(void *opaque, int version)
qxl_set_mode(d, d->shadow_rom.mode, 1);
break;
}
- dprint(d, 1, "%s: done\n", __FUNCTION__);
-
return 0;
}
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 2cb5a18..8e76c5d 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -7,6 +7,7 @@
#include "trace.h"
#include "dma.h"
+static char *scsibus_get_dev_path(DeviceState *dev);
static char *scsibus_get_fw_dev_path(DeviceState *dev);
static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf);
static void scsi_req_dequeue(SCSIRequest *req);
@@ -14,6 +15,7 @@ static void scsi_req_dequeue(SCSIRequest *req);
static struct BusInfo scsi_bus_info = {
.name = "SCSI",
.size = sizeof(SCSIBus),
+ .get_dev_path = scsibus_get_dev_path,
.get_fw_dev_path = scsibus_get_fw_dev_path,
.props = (Property[]) {
DEFINE_PROP_UINT32("channel", SCSIDevice, channel, 0),
@@ -1423,6 +1425,22 @@ void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense)
sdev->unit_attention = sense;
}
+static char *scsibus_get_dev_path(DeviceState *dev)
+{
+ SCSIDevice *d = DO_UPCAST(SCSIDevice, qdev, dev);
+ DeviceState *hba = dev->parent_bus->parent;
+ char *id = NULL;
+
+ if (hba && hba->parent_bus && hba->parent_bus->info->get_dev_path) {
+ id = hba->parent_bus->info->get_dev_path(hba);
+ }
+ if (id) {
+ return g_strdup_printf("%s/%d:%d:%d", id, d->channel, d->id, d->lun);
+ } else {
+ return g_strdup_printf("%d:%d:%d", d->channel, d->id, d->lun);
+ }
+}
+
static char *scsibus_get_fw_dev_path(DeviceState *dev)
{
SCSIDevice *d = SCSI_DEVICE(dev);
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index add399e..9949786 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -471,8 +471,9 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
case 0x83: /* Device identification page, mandatory */
{
- int max_len = 255 - 8;
- int id_len = strlen(bdrv_get_device_name(s->qdev.conf.bs));
+ const char *str = s->serial ?: bdrv_get_device_name(s->qdev.conf.bs);
+ int max_len = s->serial ? 20 : 255 - 8;
+ int id_len = strlen(str);
if (id_len > max_len) {
id_len = max_len;
@@ -486,7 +487,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
outbuf[buflen++] = 0; // reserved
outbuf[buflen++] = id_len; // length of data following
- memcpy(outbuf+buflen, bdrv_get_device_name(s->qdev.conf.bs), id_len);
+ memcpy(outbuf+buflen, str, id_len);
buflen += id_len;
break;
}
@@ -1152,9 +1153,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
outbuf = r->iov.iov_base;
switch (req->cmd.buf[0]) {
case TEST_UNIT_READY:
- if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
- goto not_ready;
- }
+ assert(!s->tray_open && bdrv_is_inserted(s->qdev.conf.bs));
break;
case INQUIRY:
buflen = scsi_disk_emulate_inquiry(req, outbuf);
@@ -1209,7 +1208,8 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
memset(outbuf, 0, 8);
bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
if (!nb_sectors) {
- goto not_ready;
+ scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
+ return -1;
}
if ((req->cmd.buf[8] & 1) == 0 && req->cmd.lba) {
goto illegal_request;
@@ -1269,7 +1269,8 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
memset(outbuf, 0, req->cmd.xfer);
bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
if (!nb_sectors) {
- goto not_ready;
+ scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
+ return -1;
}
if ((req->cmd.buf[14] & 1) == 0 && req->cmd.lba) {
goto illegal_request;
@@ -1314,14 +1315,6 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
buflen = MIN(buflen, req->cmd.xfer);
return buflen;
-not_ready:
- if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
- scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
- } else {
- scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
- }
- return -1;
-
illegal_request:
if (r->req.status == -1) {
scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
@@ -1356,6 +1349,30 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
#endif
switch (command) {
+ case INQUIRY:
+ case MODE_SENSE:
+ case MODE_SENSE_10:
+ case RESERVE:
+ case RESERVE_10:
+ case RELEASE:
+ case RELEASE_10:
+ case START_STOP:
+ case ALLOW_MEDIUM_REMOVAL:
+ case GET_CONFIGURATION:
+ case GET_EVENT_STATUS_NOTIFICATION:
+ case MECHANISM_STATUS:
+ case REQUEST_SENSE:
+ break;
+
+ default:
+ if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
+ scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
+ return 0;
+ }
+ break;
+ }
+
+ switch (command) {
case TEST_UNIT_READY:
case INQUIRY:
case MODE_SENSE:
diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index e607edc..45d54fa 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -613,5 +613,7 @@ VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
void virtio_scsi_exit(VirtIODevice *vdev)
{
+ VirtIOSCSI *s = (VirtIOSCSI *)vdev;
+ unregister_savevm(s->qdev, "virtio-scsi", s);
virtio_cleanup(vdev);
}
diff --git a/migration-fd.c b/migration-fd.c
index 5a068c6..50138ed 100644
--- a/migration-fd.c
+++ b/migration-fd.c
@@ -75,7 +75,7 @@ static int fd_close(MigrationState *s)
int fd_start_outgoing_migration(MigrationState *s, const char *fdname)
{
- s->fd = monitor_get_fd(s->mon, fdname);
+ s->fd = monitor_get_fd(cur_mon, fdname);
if (s->fd == -1) {
DPRINTF("fd_migration: invalid file descriptor identifier\n");
goto err_after_get_fd;
diff --git a/migration.c b/migration.c
index 00fa1e3..8c119ba 100644
--- a/migration.c
+++ b/migration.c
@@ -158,16 +158,6 @@ MigrationInfo *qmp_query_migrate(Error **errp)
/* shared migration helpers */
-static void migrate_fd_monitor_suspend(MigrationState *s, Monitor *mon)
-{
- if (monitor_suspend(mon) == 0) {
- DPRINTF("suspending monitor\n");
- } else {
- monitor_printf(mon, "terminal does not allow synchronous "
- "migration, continuing detached\n");
- }
-}
-
static int migrate_fd_cleanup(MigrationState *s)
{
int ret = 0;
@@ -178,10 +168,6 @@ static int migrate_fd_cleanup(MigrationState *s)
DPRINTF("closing file\n");
ret = qemu_fclose(s->file);
s->file = NULL;
- } else {
- if (s->mon) {
- monitor_resume(s->mon);
- }
}
if (s->fd != -1) {
@@ -258,7 +244,7 @@ static void migrate_fd_put_ready(void *opaque)
}
DPRINTF("iterate\n");
- ret = qemu_savevm_state_iterate(s->mon, s->file);
+ ret = qemu_savevm_state_iterate(s->file);
if (ret < 0) {
migrate_fd_error(s);
} else if (ret == 1) {
@@ -267,7 +253,7 @@ static void migrate_fd_put_ready(void *opaque)
DPRINTF("done iterating\n");
vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
- if (qemu_savevm_state_complete(s->mon, s->file) < 0) {
+ if (qemu_savevm_state_complete(s->file) < 0) {
migrate_fd_error(s);
} else {
migrate_fd_completed(s);
@@ -289,7 +275,7 @@ static void migrate_fd_cancel(MigrationState *s)
s->state = MIG_STATE_CANCELLED;
notifier_list_notify(&migration_state_notifiers, s);
- qemu_savevm_state_cancel(s->mon, s->file);
+ qemu_savevm_state_cancel(s->file);
migrate_fd_cleanup(s);
}
@@ -321,9 +307,6 @@ static int migrate_fd_close(void *opaque)
{
MigrationState *s = opaque;
- if (s->mon) {
- monitor_resume(s->mon);
- }
qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
return s->close(s);
}
@@ -367,7 +350,7 @@ void migrate_fd_connect(MigrationState *s)
migrate_fd_close);
DPRINTF("beginning savevm\n");
- ret = qemu_savevm_state_begin(s->mon, s->file, s->blk, s->shared);
+ ret = qemu_savevm_state_begin(s->file, s->blk, s->shared);
if (ret < 0) {
DPRINTF("failed, %d\n", ret);
migrate_fd_error(s);
@@ -376,7 +359,7 @@ void migrate_fd_connect(MigrationState *s)
migrate_fd_put_ready(s);
}
-static MigrationState *migrate_init(Monitor *mon, int detach, int blk, int inc)
+static MigrationState *migrate_init(int blk, int inc)
{
MigrationState *s = migrate_get_current();
int64_t bandwidth_limit = s->bandwidth_limit;
@@ -386,18 +369,9 @@ static MigrationState *migrate_init(Monitor *mon, int detach, int blk, int inc)
s->blk = blk;
s->shared = inc;
- /* s->mon is used for two things:
- - pass fd in fd migration
- - suspend/resume monitor for not detached migration
- */
- s->mon = mon;
s->bandwidth_limit = bandwidth_limit;
s->state = MIG_STATE_SETUP;
- if (!detach) {
- migrate_fd_monitor_suspend(s, mon);
- }
-
return s;
}
@@ -413,32 +387,29 @@ void migrate_del_blocker(Error *reason)
migration_blockers = g_slist_remove(migration_blockers, reason);
}
-int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_migrate(const char *uri, bool has_blk, bool blk,
+ bool has_inc, bool inc, bool has_detach, bool detach,
+ Error **errp)
{
MigrationState *s = migrate_get_current();
const char *p;
- int detach = qdict_get_try_bool(qdict, "detach", 0);
- int blk = qdict_get_try_bool(qdict, "blk", 0);
- int inc = qdict_get_try_bool(qdict, "inc", 0);
- const char *uri = qdict_get_str(qdict, "uri");
int ret;
if (s->state == MIG_STATE_ACTIVE) {
- monitor_printf(mon, "migration already in progress\n");
- return -1;
+ error_set(errp, QERR_MIGRATION_ACTIVE);
+ return;
}
- if (qemu_savevm_state_blocked(mon)) {
- return -1;
+ if (qemu_savevm_state_blocked(errp)) {
+ return;
}
if (migration_blockers) {
- Error *err = migration_blockers->data;
- qerror_report_err(err);
- return -1;
+ *errp = error_copy(migration_blockers->data);
+ return;
}
- s = migrate_init(mon, detach, blk, inc);
+ s = migrate_init(blk, inc);
if (strstart(uri, "tcp:", &p)) {
ret = tcp_start_outgoing_migration(s, p);
@@ -451,21 +422,18 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
ret = fd_start_outgoing_migration(s, p);
#endif
} else {
- monitor_printf(mon, "unknown migration protocol: %s\n", uri);
- ret = -EINVAL;
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE, "uri", "a valid migration protocol");
+ return;
}
if (ret < 0) {
- monitor_printf(mon, "migration failed: %s\n", strerror(-ret));
- return ret;
- }
-
- if (detach) {
- s->mon = NULL;
+ DPRINTF("migration failed: %s\n", strerror(-ret));
+ /* FIXME: we should return meaningful errors */
+ error_set(errp, QERR_UNDEFINED_ERROR);
+ return;
}
notifier_list_notify(&migration_state_notifiers, s);
- return 0;
}
void qmp_migrate_cancel(Error **errp)
diff --git a/migration.h b/migration.h
index 372b066..691b367 100644
--- a/migration.h
+++ b/migration.h
@@ -26,7 +26,6 @@ struct MigrationState
int64_t bandwidth_limit;
QEMUFile *file;
int fd;
- Monitor *mon;
int state;
int (*get_error)(MigrationState *s);
int (*close)(MigrationState *s);
@@ -40,8 +39,6 @@ void process_incoming_migration(QEMUFile *f);
int qemu_start_incoming_migration(const char *uri);
-int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data);
-
uint64_t migrate_max_downtime(void);
void do_info_migrate_print(Monitor *mon, const QObject *data);
@@ -78,7 +75,7 @@ uint64_t ram_bytes_remaining(void);
uint64_t ram_bytes_transferred(void);
uint64_t ram_bytes_total(void);
-int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque);
+int ram_save_live(QEMUFile *f, int stage, void *opaque);
int ram_load(QEMUFile *f, void *opaque, int version_id);
/**
diff --git a/monitor.c b/monitor.c
index e71a141..2ff1e0b 100644
--- a/monitor.c
+++ b/monitor.c
@@ -879,6 +879,11 @@ static int client_migrate_info(Monitor *mon, const QDict *qdict,
return -1;
}
+ if (port == -1 && tls_port == -1) {
+ qerror_report(QERR_MISSING_PARAMETER, "port/tls-port");
+ return -1;
+ }
+
ret = qemu_spice_migrate_info(hostname, port, tls_port, subject,
cb, opaque);
if (ret != 0) {
diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index 41e2b38..e1f3923 100644
--- a/pc-bios/bios.bin
+++ b/pc-bios/bios.bin
Binary files differ
diff --git a/qapi-schema.json b/qapi-schema.json
index 04fa84f..3a962c1 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1663,3 +1663,24 @@
{ 'command': 'qom-list-types',
'data': { '*implements': 'str', '*abstract': 'bool' },
'returns': [ 'ObjectTypeInfo' ] }
+
+##
+# @migrate
+#
+# Migrates the current running guest to another Virtual Machine.
+#
+# @uri: the Uniform Resource Identifier of the destination VM
+#
+# @blk: #optional do block migration (full disk copy)
+#
+# @inc: #optional incremental disk copy migration
+#
+# @detach: this argument exists only for compatibility reasons and
+# is ignored by QEMU
+#
+# Returns: nothing on success
+#
+# Since: 0.14.0
+##
+{ 'command': 'migrate',
+ 'data': {'uri': 'str', '*blk': 'bool', '*inc': 'bool', '*detach': 'bool' } }
diff --git a/qerror.c b/qerror.c
index f55d435..41c729a 100644
--- a/qerror.c
+++ b/qerror.c
@@ -193,6 +193,14 @@ static const QErrorStringTable qerror_table[] = {
.desc = "Using KVM without %(capability), %(feature) unavailable",
},
{
+ .error_fmt = QERR_MIGRATION_ACTIVE,
+ .desc = "There's a migration process in progress",
+ },
+ {
+ .error_fmt = QERR_MIGRATION_NOT_SUPPORTED,
+ .desc = "State blocked by non-migratable device '%(device)'",
+ },
+ {
.error_fmt = QERR_MIGRATION_EXPECTED,
.desc = "An incoming migration is expected before this command can be executed",
},
diff --git a/qerror.h b/qerror.h
index e26c635..e16f9c2 100644
--- a/qerror.h
+++ b/qerror.h
@@ -166,6 +166,12 @@ QError *qobject_to_qerror(const QObject *obj);
#define QERR_KVM_MISSING_CAP \
"{ 'class': 'KVMMissingCap', 'data': { 'capability': %s, 'feature': %s } }"
+#define QERR_MIGRATION_ACTIVE \
+ "{ 'class': 'MigrationActive', 'data': {} }"
+
+#define QERR_MIGRATION_NOT_SUPPORTED \
+ "{ 'class': 'MigrationNotSupported', 'data': {'device': %s} }"
+
#define QERR_MIGRATION_EXPECTED \
"{ 'class': 'MigrationExpected', 'data': {} }"
diff --git a/qmp-commands.hx b/qmp-commands.hx
index dfe8a5b..8b82038 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -446,14 +446,7 @@ EQMP
{
.name = "migrate",
.args_type = "detach:-d,blk:-b,inc:-i,uri:s",
- .params = "[-d] [-b] [-i] uri",
- .help = "migrate to URI (using -d to not wait for completion)"
- "\n\t\t\t -b for migration without shared storage with"
- " full copy of disk\n\t\t\t -i for migration without "
- "shared storage with incremental copy of disk "
- "(base image shared between src and destination)",
- .user_print = monitor_user_noop,
- .mhandler.cmd_new = do_migrate,
+ .mhandler.cmd_new = qmp_marshal_input_migrate,
},
SQMP
diff --git a/roms/Makefile b/roms/Makefile
new file mode 100644
index 0000000..0114e6f
--- /dev/null
+++ b/roms/Makefile
@@ -0,0 +1,10 @@
+
+default:
+ @echo "nothing is build by default"
+ @echo "available build targets:"
+ @echo " bios -- update bios.bin (seabios)"
+
+bios: config.seabios
+ sh configure-seabios.sh $<
+ make -C seabios out/bios.bin
+ cp seabios/out/bios.bin ../pc-bios/bios.bin
diff --git a/roms/config.seabios b/roms/config.seabios
new file mode 100644
index 0000000..c373b87
--- /dev/null
+++ b/roms/config.seabios
@@ -0,0 +1 @@
+# empty, default config works for us
diff --git a/roms/configure-seabios.sh b/roms/configure-seabios.sh
new file mode 100755
index 0000000..98f59a2
--- /dev/null
+++ b/roms/configure-seabios.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+config="$1"
+make -C seabios clean distclean
+cp "$config" seabios/.config
+make -C seabios oldnoconfig
diff --git a/roms/seabios b/roms/seabios
-Subproject 80d11e8577bf03e98f2eb1b0cb3a281ab2879c9
+Subproject 2e8bd611ce4e1e36b5a80c9ca6e256e23802f09
diff --git a/savevm.c b/savevm.c
index 694eaa4..962175a 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1542,22 +1542,20 @@ static void vmstate_save(QEMUFile *f, SaveStateEntry *se)
#define QEMU_VM_SECTION_FULL 0x04
#define QEMU_VM_SUBSECTION 0x05
-bool qemu_savevm_state_blocked(Monitor *mon)
+bool qemu_savevm_state_blocked(Error **errp)
{
SaveStateEntry *se;
QTAILQ_FOREACH(se, &savevm_handlers, entry) {
if (se->no_migrate) {
- monitor_printf(mon, "state blocked by non-migratable device '%s'\n",
- se->idstr);
+ error_set(errp, QERR_MIGRATION_NOT_SUPPORTED, se->idstr);
return true;
}
}
return false;
}
-int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
- int shared)
+int qemu_savevm_state_begin(QEMUFile *f, int blk_enable, int shared)
{
SaveStateEntry *se;
int ret;
@@ -1590,15 +1588,15 @@ int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
qemu_put_be32(f, se->instance_id);
qemu_put_be32(f, se->version_id);
- ret = se->save_live_state(mon, f, QEMU_VM_SECTION_START, se->opaque);
+ ret = se->save_live_state(f, QEMU_VM_SECTION_START, se->opaque);
if (ret < 0) {
- qemu_savevm_state_cancel(mon, f);
+ qemu_savevm_state_cancel(f);
return ret;
}
}
ret = qemu_file_get_error(f);
if (ret != 0) {
- qemu_savevm_state_cancel(mon, f);
+ qemu_savevm_state_cancel(f);
}
return ret;
@@ -1611,7 +1609,7 @@ int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
* 0 : We haven't finished, caller have to go again
* 1 : We have finished, we can go to complete phase
*/
-int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
+int qemu_savevm_state_iterate(QEMUFile *f)
{
SaveStateEntry *se;
int ret = 1;
@@ -1624,7 +1622,7 @@ int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
qemu_put_byte(f, QEMU_VM_SECTION_PART);
qemu_put_be32(f, se->section_id);
- ret = se->save_live_state(mon, f, QEMU_VM_SECTION_PART, se->opaque);
+ ret = se->save_live_state(f, QEMU_VM_SECTION_PART, se->opaque);
if (ret <= 0) {
/* Do not proceed to the next vmstate before this one reported
completion of the current stage. This serializes the migration
@@ -1638,12 +1636,12 @@ int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
}
ret = qemu_file_get_error(f);
if (ret != 0) {
- qemu_savevm_state_cancel(mon, f);
+ qemu_savevm_state_cancel(f);
}
return ret;
}
-int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
+int qemu_savevm_state_complete(QEMUFile *f)
{
SaveStateEntry *se;
int ret;
@@ -1658,7 +1656,7 @@ int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
qemu_put_byte(f, QEMU_VM_SECTION_END);
qemu_put_be32(f, se->section_id);
- ret = se->save_live_state(mon, f, QEMU_VM_SECTION_END, se->opaque);
+ ret = se->save_live_state(f, QEMU_VM_SECTION_END, se->opaque);
if (ret < 0) {
return ret;
}
@@ -1690,37 +1688,37 @@ int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
return qemu_file_get_error(f);
}
-void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f)
+void qemu_savevm_state_cancel(QEMUFile *f)
{
SaveStateEntry *se;
QTAILQ_FOREACH(se, &savevm_handlers, entry) {
if (se->save_live_state) {
- se->save_live_state(mon, f, -1, se->opaque);
+ se->save_live_state(f, -1, se->opaque);
}
}
}
-static int qemu_savevm_state(Monitor *mon, QEMUFile *f)
+static int qemu_savevm_state(QEMUFile *f)
{
int ret;
- if (qemu_savevm_state_blocked(mon)) {
+ if (qemu_savevm_state_blocked(NULL)) {
ret = -EINVAL;
goto out;
}
- ret = qemu_savevm_state_begin(mon, f, 0, 0);
+ ret = qemu_savevm_state_begin(f, 0, 0);
if (ret < 0)
goto out;
do {
- ret = qemu_savevm_state_iterate(mon, f);
+ ret = qemu_savevm_state_iterate(f);
if (ret < 0)
goto out;
} while (ret == 0);
- ret = qemu_savevm_state_complete(mon, f);
+ ret = qemu_savevm_state_complete(f);
out:
if (ret == 0) {
@@ -1839,7 +1837,7 @@ int qemu_loadvm_state(QEMUFile *f)
unsigned int v;
int ret;
- if (qemu_savevm_state_blocked(default_mon)) {
+ if (qemu_savevm_state_blocked(NULL)) {
return -EINVAL;
}
@@ -2083,7 +2081,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)
monitor_printf(mon, "Could not open VM state file\n");
goto the_end;
}
- ret = qemu_savevm_state(mon, f);
+ ret = qemu_savevm_state(f);
vm_state_size = qemu_ftell(f);
qemu_fclose(f);
if (ret < 0) {
diff --git a/sysemu.h b/sysemu.h
index 98118cc..bc2c788 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -76,12 +76,11 @@ void do_info_snapshots(Monitor *mon);
void qemu_announce_self(void);
-bool qemu_savevm_state_blocked(Monitor *mon);
-int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
- int shared);
-int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f);
-int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f);
-void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f);
+bool qemu_savevm_state_blocked(Error **errp);
+int qemu_savevm_state_begin(QEMUFile *f, int blk_enable, int shared);
+int qemu_savevm_state_iterate(QEMUFile *f);
+int qemu_savevm_state_complete(QEMUFile *f);
+void qemu_savevm_state_cancel(QEMUFile *f);
int qemu_loadvm_state(QEMUFile *f);
/* SLIRP */
diff --git a/trace-events b/trace-events
index c8317a0..70f059d 100644
--- a/trace-events
+++ b/trace-events
@@ -722,3 +722,69 @@ displaysurface_resize(void *display_state, void *display_surface, int width, int
# vga.c
ppm_save(const char *filename, void *display_surface) "%s surface=%p"
+
+# hw/qxl.c
+disable qxl_interface_set_mm_time(int qid, uint32_t mm_time) "%d %d"
+disable qxl_io_write_vga(int qid, const char *mode, uint32_t addr, uint32_t val) "%d %s addr=%u val=%u"
+qxl_create_guest_primary(int qid, uint32_t width, uint32_t height, uint64_t mem, uint32_t format, uint32_t position) "%d %dx%d mem=%lx %d,%d"
+qxl_create_guest_primary_rest(int qid, int32_t stride, uint32_t type, uint32_t flags) "%d %d,%d,%d"
+qxl_destroy_primary(int qid) "%d"
+qxl_enter_vga_mode(int qid) "%d"
+qxl_exit_vga_mode(int qid) "%d"
+qxl_hard_reset(int qid, int64_t loadvm) "%d loadvm=%"PRId64""
+qxl_interface_async_complete_io(int qid, uint32_t current_async, void *cookie) "%d current=%d cookie=%p"
+qxl_interface_attach_worker(int qid) "%d"
+qxl_interface_get_init_info(int qid) "%d"
+qxl_interface_set_compression_level(int qid, int64_t level) "%d %"PRId64
+qxl_interface_update_area_complete(int qid, uint32_t surface_id, uint32_t dirty_left, uint32_t dirty_right, uint32_t dirty_top, uint32_t dirty_bottom) "%d surface=%d [%d,%d,%d,%d]"
+qxl_interface_update_area_complete_rest(int qid, uint32_t num_updated_rects) "%d #=%d"
+qxl_interface_update_area_complete_overflow(int qid, int max) "%d max=%d"
+qxl_interface_update_area_complete_schedule_bh(int qid, uint32_t num_dirty) "%d #dirty=%d"
+qxl_io_destroy_primary_ignored(int qid, const char *mode) "%d %s"
+qxl_io_read_unexpected(int qid) "%d"
+qxl_io_unexpected_vga_mode(int qid, uint32_t io_port, const char *desc) "%d 0x%x (%s)"
+qxl_io_write(int qid, const char *mode, uint64_t addr, uint64_t val, unsigned size, int async) "%d %s addr=%"PRIu64 " val=%"PRIu64" size=%u async=%d"
+qxl_memslot_add_guest(int qid, uint32_t slot_id, uint64_t guest_start, uint64_t guest_end) "%d %u: guest phys 0x%"PRIx64 " - 0x%" PRIx64
+qxl_post_load(int qid, const char *mode) "%d %s"
+qxl_pre_load(int qid) "%d"
+qxl_pre_save(int qid) "%d"
+qxl_reset_surfaces(int qid) "%d"
+qxl_ring_command_check(int qid, const char *mode) "%d %s"
+qxl_ring_command_get(int qid, const char *mode) "%d %s"
+qxl_ring_command_req_notification(int qid) "%d"
+qxl_ring_cursor_check(int qid, const char *mode) "%d %s"
+qxl_ring_cursor_get(int qid, const char *mode) "%d %s"
+qxl_ring_cursor_req_notification(int qid) "%d"
+qxl_ring_res_push(int qid, const char *mode, uint32_t surface_count, uint32_t free_res, void *last_release, const char *notify) "%d %s s#=%d res#=%d last=%p notify=%s"
+qxl_ring_res_push_rest(int qid, uint32_t ring_has, uint32_t ring_size, uint32_t prod, uint32_t cons) "%d ring %d/%d [%d,%d]"
+qxl_ring_res_put(int qid, uint32_t free_res) "%d #res=%d"
+qxl_set_mode(int qid, int modenr, uint32_t x_res, uint32_t y_res, uint32_t bits, uint64_t devmem) "%d mode=%d [ x=%d y=%d @ bpp=%d devmem=0x%" PRIx64 " ]"
+qxl_soft_reset(int qid) "%d"
+qemu_spice_add_memslot(int qid, uint32_t slot_id, unsigned long virt_start, unsigned long virt_end, int async) "%d %u: host virt 0x%lx - 0x%lx async=%d"
+qemu_spice_del_memslot(int qid, uint32_t gid, uint32_t slot_id) "%d gid=%u sid=%u"
+qemu_spice_create_primary_surface(int qid, uint32_t sid, void *surface, int async) "%d sid=%u surface=%p async=%d"
+qemu_spice_destroy_primary_surface(int qid, uint32_t sid, int async) "%d sid=%u async=%d"
+qemu_spice_wakeup(uint32_t qid) "%d"
+qemu_spice_start(uint32_t qid) "%d"
+qemu_spice_stop(uint32_t qid) "%d"
+qemu_spice_create_update(uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) "lr %d -> %d, tb -> %d -> %d"
+qxl_spice_destroy_surfaces_complete(int qid) "%d"
+qxl_spice_destroy_surfaces(int qid, int async) "%d async=%d"
+qxl_spice_destroy_surface_wait_complete(int qid, uint32_t id) "%d sid=%d"
+qxl_spice_destroy_surface_wait(int qid, uint32_t id, int async) "%d sid=%d async=%d"
+qxl_spice_flush_surfaces_async(int qid, uint32_t surface_count, uint32_t num_free_res) "%d s#=%d, res#=%d"
+qxl_spice_loadvm_commands(int qid, void *ext, uint32_t count) "%d ext=%p count=%d"
+qxl_spice_oom(int qid) "%d"
+qxl_spice_reset_cursor(int qid) "%d"
+qxl_spice_reset_image_cache(int qid) "%d"
+qxl_spice_reset_memslots(int qid) "%d"
+qxl_spice_update_area(int qid, uint32_t surface_id, uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) "%d sid=%d [%d,%d,%d,%d]"
+qxl_spice_update_area_rest(int qid, uint32_t num_dirty_rects, uint32_t clear_dirty_region) "%d #d=%d clear=%d"
+qxl_surfaces_dirty(int qid, int surface, int offset, int size) "%d surface=%d offset=%d size=%d"
+qxl_vga_ioport_while_not_in_vga_mode(int qid) "%d (int qid, reset to VGA mode because of VGA io)"
+
+# hw/qxl-render.c
+qxl_render_blit_guest_primary_initialized(void) ""
+qxl_render_blit(int32_t stride, int32_t left, int32_t right, int32_t top, int32_t bottom) "stride=%d [%d, %d, %d, %d]"
+qxl_render_guest_primary_resized(int32_t width, int32_t height, int32_t stride, int32_t bytes_pp, int32_t bits_pp) "%dx%d, stride %d, bpp %d, depth %d"
+qxl_render_update_area_done(void *cookie) "%p"
diff --git a/ui/spice-core.c b/ui/spice-core.c
index c1091e1..a468524 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -19,6 +19,7 @@
#include <spice-experimental.h>
#include <netdb.h>
+#include "sysemu.h"
#include "qemu-common.h"
#include "qemu-spice.h"
@@ -553,7 +554,7 @@ void qemu_spice_init(void)
qemu_thread_get_self(&me);
- if (!opts) {
+ if (!opts) {
return;
}
port = qemu_opt_get_number(opts, "port", 0);
@@ -688,6 +689,11 @@ void qemu_spice_init(void)
qemu_opt_foreach(opts, add_channel, &tls_port, 0);
+#if SPICE_SERVER_VERSION >= 0x000a02 /* 0.10.2 */
+ spice_server_set_name(spice_server, qemu_name);
+ spice_server_set_uuid(spice_server, qemu_uuid);
+#endif
+
if (0 != spice_server_init(spice_server, &core_interface)) {
error_report("failed to initialize spice server");
exit(1);
@@ -781,10 +787,3 @@ static void spice_register_config(void)
qemu_add_opts(&qemu_spice_opts);
}
machine_init(spice_register_config);
-
-static void spice_register_types(void)
-{
- qemu_spice_init();
-}
-
-type_init(spice_register_types)
diff --git a/ui/spice-display.c b/ui/spice-display.c
index ab266ae..28d6d4a 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -22,6 +22,7 @@
#include "monitor.h"
#include "console.h"
#include "sysemu.h"
+#include "trace.h"
#include "spice-display.h"
@@ -73,6 +74,10 @@ QXLCookie *qxl_cookie_new(int type, uint64_t io)
void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot,
qxl_async_io async)
{
+ trace_qemu_spice_add_memslot(ssd->qxl.id, memslot->slot_id,
+ memslot->virt_start, memslot->virt_end,
+ async);
+
if (async != QXL_SYNC) {
spice_qxl_add_memslot_async(&ssd->qxl, memslot,
(uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
@@ -84,6 +89,7 @@ void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot,
void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid, uint32_t sid)
{
+ trace_qemu_spice_del_memslot(ssd->qxl.id, gid, sid);
ssd->worker->del_memslot(ssd->worker, gid, sid);
}
@@ -91,6 +97,7 @@ void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
QXLDevSurfaceCreate *surface,
qxl_async_io async)
{
+ 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,
(uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
@@ -100,10 +107,10 @@ void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
}
}
-
void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd,
uint32_t id, qxl_async_io async)
{
+ trace_qemu_spice_destroy_primary_surface(ssd->qxl.id, id, async);
if (async != QXL_SYNC) {
spice_qxl_destroy_primary_surface_async(&ssd->qxl, id,
(uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
@@ -115,16 +122,19 @@ void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd,
void qemu_spice_wakeup(SimpleSpiceDisplay *ssd)
{
+ trace_qemu_spice_wakeup(ssd->qxl.id);
ssd->worker->wakeup(ssd->worker);
}
void qemu_spice_start(SimpleSpiceDisplay *ssd)
{
+ trace_qemu_spice_start(ssd->qxl.id);
ssd->worker->start(ssd->worker);
}
void qemu_spice_stop(SimpleSpiceDisplay *ssd)
{
+ trace_qemu_spice_stop(ssd->qxl.id);
ssd->worker->stop(ssd->worker);
}
@@ -142,7 +152,7 @@ static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
return NULL;
};
- dprint(2, "%s: lr %d -> %d, tb -> %d -> %d\n", __FUNCTION__,
+ trace_qemu_spice_create_update(
ssd->dirty.left, ssd->dirty.right,
ssd->dirty.top, ssd->dirty.bottom);
diff --git a/vl.c b/vl.c
index bd95539..eeb634b 100644
--- a/vl.c
+++ b/vl.c
@@ -3369,6 +3369,11 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
+#ifdef CONFIG_SPICE
+ /* spice needs the timers to be initialized by this point */
+ qemu_spice_init();
+#endif
+
if (icount_option && (kvm_enabled() || xen_enabled())) {
fprintf(stderr, "-icount is not allowed with kvm or xen\n");
exit(1);
diff --git a/vmstate.h b/vmstate.h
index 9d3c49c..82d97ae 100644
--- a/vmstate.h
+++ b/vmstate.h
@@ -28,8 +28,7 @@
typedef void SaveSetParamsHandler(int blk_enable, int shared, void * opaque);
typedef void SaveStateHandler(QEMUFile *f, void *opaque);
-typedef int SaveLiveStateHandler(Monitor *mon, QEMUFile *f, int stage,
- void *opaque);
+typedef int SaveLiveStateHandler(QEMUFile *f, int stage, void *opaque);
typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id);
int register_savevm(DeviceState *dev,