#include "qemu/bitmap.h"
#include "qemu/seqlock.h"
#include "qapi-event.h"
+#include "hw/nmi.h"
#ifndef _WIN32
#include "qemu/compatfd.h"
#endif /* CONFIG_LINUX */
static CPUState *next_cpu;
+int64_t max_delay;
+int64_t max_advance;
bool cpu_is_stopped(CPUState *cpu)
{
/* Protected by TimersState seqlock */
-static int64_t vm_clock_warp_start;
+static int64_t vm_clock_warp_start = -1;
/* Conversion factor from emulated instructions to virtual clock ticks. */
static int icount_time_shift;
/* Arbitrarily pick 1MIPS as the minimum allowable speed. */
return ti;
}
+/* return the offset between the host clock and virtual CPU clock */
+int64_t cpu_get_clock_offset(void)
+{
+ int64_t ti;
+ unsigned start;
+
+ do {
+ start = seqlock_read_begin(&timers_state.vm_clock_seqlock);
+ ti = timers_state.cpu_clock_offset;
+ if (!timers_state.cpu_ticks_enabled) {
+ ti -= get_clock();
+ }
+ } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start));
+
+ return -ti;
+}
+
/* enable cpu_get_ticks()
* Caller must hold BQL which server as mutex for vm_clock_seqlock.
*/
}
};
-void configure_icount(const char *option)
+void cpu_ticks_init(void)
{
seqlock_init(&timers_state.vm_clock_seqlock, NULL);
vmstate_register(NULL, 0, &vmstate_timers, &timers_state);
+}
+
+void configure_icount(QemuOpts *opts, Error **errp)
+{
+ const char *option;
+ char *rem_str = NULL;
+
+ 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;
}
-
+ 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;
#elif defined(TARGET_MIPS)
MIPSCPU *mips_cpu = MIPS_CPU(cpu);
CPUMIPSState *env = &mips_cpu->env;
+#elif defined(TARGET_TRICORE)
+ TriCoreCPU *tricore_cpu = TRICORE_CPU(cpu);
+ CPUTriCoreState *env = &tricore_cpu->env;
#endif
cpu_synchronize_state(cpu);
#elif defined(TARGET_MIPS)
info->value->has_PC = true;
info->value->PC = env->active_tc.PC;
+#elif defined(TARGET_TRICORE)
+ info->value->has_PC = true;
+ info->value->PC = env->PC;
#endif
/* XXX: waiting for the qapi to support GSList */
apic_deliver_nmi(cpu->apic_state);
}
}
-#elif defined(TARGET_S390X)
- CPUState *cs;
- S390CPU *cpu;
-
- CPU_FOREACH(cs) {
- cpu = S390_CPU(cs);
- if (cpu->env.cpu_num == monitor_get_cpu_index()) {
- if (s390_cpu_restart(S390_CPU(cs)) == -1) {
- error_set(errp, QERR_UNSUPPORTED);
- return;
- }
- break;
- }
- }
#else
- error_set(errp, QERR_UNSUPPORTED);
+ nmi_monitor_handle(monitor_get_cpu_index(), errp);
#endif
}
+
+void dump_drift_info(FILE *f, fprintf_function cpu_fprintf)
+{
+ if (!use_icount) {
+ return;
+ }
+
+ cpu_fprintf(f, "Host - Guest clock %"PRIi64" ms\n",
+ (cpu_get_clock() - cpu_get_icount())/SCALE_MS);
+ if (icount_align_option) {
+ cpu_fprintf(f, "Max guest delay %"PRIi64" ms\n", -max_delay/SCALE_MS);
+ cpu_fprintf(f, "Max guest advance %"PRIi64" ms\n", max_advance/SCALE_MS);
+ } else {
+ cpu_fprintf(f, "Max guest delay NA\n");
+ cpu_fprintf(f, "Max guest advance NA\n");
+ }
+}