diff --git a/cpus.c b/cpus.c index 82910442039ec351d86b608e4aee04492c0647d4..7e09538799ed696ca502069a7ff7b29182d26466 100644 --- a/cpus.c +++ b/cpus.c @@ -476,25 +476,30 @@ static const VMStateDescription vmstate_timers = { void configure_icount(QemuOpts *opts, Error **errp) { const char *option; + char *rem_str = NULL; seqlock_init(&timers_state.vm_clock_seqlock, NULL); vmstate_register(NULL, 0, &vmstate_timers, &timers_state); option = qemu_opt_get(opts, "shift"); if (!option) { + if (qemu_opt_get(opts, "align") != NULL) { + error_setg(errp, "Please specify shift option when using align"); + } return; } - /* When using -icount shift, the shift option will be - misinterpreted as a boolean */ - if (strcmp(option, "on") == 0 || strcmp(option, "off") == 0) { - error_setg(errp, "The shift option must be a number or auto"); - } - + icount_align_option = qemu_opt_get_bool(opts, "align", false); icount_warp_timer = timer_new_ns(QEMU_CLOCK_REALTIME, icount_warp_rt, NULL); if (strcmp(option, "auto") != 0) { - icount_time_shift = strtol(option, NULL, 0); + errno = 0; + icount_time_shift = strtol(option, &rem_str, 0); + if (errno != 0 || *rem_str != '\0' || !strlen(option)) { + error_setg(errp, "icount: Invalid shift value"); + } use_icount = 1; return; + } else if (icount_align_option) { + error_setg(errp, "shift=auto and align=on are incompatible"); } use_icount = 2; diff --git a/include/qemu-common.h b/include/qemu-common.h index 04b0769c4744760d84dc00327c1f82a0ad70d3f8..5d10ac27a1861364f87f8c4d8d81e2af1a9d1074 100644 --- a/include/qemu-common.h +++ b/include/qemu-common.h @@ -108,6 +108,7 @@ static inline char *realpath(const char *path, char *resolved_path) /* icount */ void configure_icount(QemuOpts *opts, Error **errp); extern int use_icount; +extern int icount_align_option; #include "qemu/osdep.h" #include "qemu/bswap.h" diff --git a/qemu-options.hx b/qemu-options.hx index 5a1b0018816e567f4fa31e36e2192785a986668e..96516c1e23c1a3017bc62cc2748ce286b0720a28 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -3011,9 +3011,9 @@ re-inject them. ETEXI DEF("icount", HAS_ARG, QEMU_OPTION_icount, \ - "-icount [shift=N|auto]\n" \ + "-icount [shift=N|auto][,align=on|off]\n" \ " enable virtual instruction counter with 2^N clock ticks per\n" \ - " instruction\n", QEMU_ARCH_ALL) + " instruction and enable aligning the host and virtual clocks\n", QEMU_ARCH_ALL) STEXI @item -icount [shift=@var{N}|auto] @findex -icount @@ -3026,6 +3026,17 @@ Note that while this option can give deterministic behavior, it does not provide cycle accurate emulation. Modern CPUs contain superscalar out of order cores with complex cache hierarchies. The number of instructions executed often has little or no correlation with actual performance. + +@option{align=on} will activate the delay algorithm which will try to +to synchronise the host clock and the virtual clock. The goal is to +have a guest running at the real frequency imposed by the shift option. +Whenever the guest clock is behind the host clock and if +@option{align=on} is specified then we print a messsage to the user +to inform about the delay. +Currently this option does not work when @option{shift} is @code{auto}. +Note: The sync algorithm will work for those shift values for which +the guest clock runs ahead of the host clock. Typically this happens +when the shift value is high (how high depends on the host machine). ETEXI DEF("watchdog", HAS_ARG, QEMU_OPTION_watchdog, \ diff --git a/vl.c b/vl.c index f2621a50dbf6eee562fdec3d89956babc194727e..a8029d59d7d135c5fd1d0186eb7dab5d36d73576 100644 --- a/vl.c +++ b/vl.c @@ -183,6 +183,7 @@ uint8_t *boot_splash_filedata; size_t boot_splash_filedata_size; uint8_t qemu_extra_params_fw[2]; +int icount_align_option; typedef struct FWBootEntry FWBootEntry; struct FWBootEntry { @@ -546,6 +547,9 @@ static QemuOptsList qemu_icount_opts = { { .name = "shift", .type = QEMU_OPT_STRING, + }, { + .name = "align", + .type = QEMU_OPT_BOOL, }, { /* end of list */ } },