diff options
-rw-r--r-- | Makefile.target | 2 | ||||
-rw-r--r-- | arch_init.c | 2 | ||||
-rw-r--r-- | block-migration.c | 58 | ||||
-rw-r--r-- | default-configs/pci.mak | 1 | ||||
-rw-r--r-- | default-configs/s390x-softmmu.mak | 1 | ||||
-rw-r--r-- | error.c | 13 | ||||
-rw-r--r-- | error.h | 5 | ||||
-rw-r--r-- | exec.c | 18 | ||||
-rw-r--r-- | hmp-commands.hx | 3 | ||||
-rw-r--r-- | hmp.c | 74 | ||||
-rw-r--r-- | hmp.h | 1 | ||||
-rw-r--r-- | hw/pci.c | 1 | ||||
-rw-r--r-- | hw/qxl-render.c | 13 | ||||
-rw-r--r-- | hw/qxl.c | 176 | ||||
-rw-r--r-- | hw/scsi-bus.c | 18 | ||||
-rw-r--r-- | hw/scsi-disk.c | 49 | ||||
-rw-r--r-- | hw/virtio-scsi.c | 2 | ||||
-rw-r--r-- | migration-fd.c | 2 | ||||
-rw-r--r-- | migration.c | 74 | ||||
-rw-r--r-- | migration.h | 5 | ||||
-rw-r--r-- | monitor.c | 5 | ||||
-rw-r--r-- | pc-bios/bios.bin | bin | 131072 -> 131072 bytes | |||
-rw-r--r-- | qapi-schema.json | 21 | ||||
-rw-r--r-- | qerror.c | 8 | ||||
-rw-r--r-- | qerror.h | 6 | ||||
-rw-r--r-- | qmp-commands.hx | 9 | ||||
-rw-r--r-- | roms/Makefile | 10 | ||||
-rw-r--r-- | roms/config.seabios | 1 | ||||
-rwxr-xr-x | roms/configure-seabios.sh | 5 | ||||
m--------- | roms/seabios | 0 | ||||
-rw-r--r-- | savevm.c | 42 | ||||
-rw-r--r-- | sysemu.h | 11 | ||||
-rw-r--r-- | trace-events | 66 | ||||
-rw-r--r-- | ui/spice-core.c | 15 | ||||
-rw-r--r-- | ui/spice-display.c | 14 | ||||
-rw-r--r-- | vl.c | 5 | ||||
-rw-r--r-- | vmstate.h | 3 |
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 @@ -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); @@ -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); @@ -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, }, @@ -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)); + } +} @@ -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 @@ -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); @@ -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); /** @@ -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 Binary files differindex 41e2b38..e1f3923 100644 --- a/pc-bios/bios.bin +++ b/pc-bios/bios.bin 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' } } @@ -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", }, @@ -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 @@ -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) { @@ -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); @@ -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); @@ -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, |