} else {
/* divide each RTC interval to 2 - 8 smaller intervals */
int c = MIN(s->irq_coalesced, 7) + 1;
- int64_t next_clock = qemu_get_clock(vm_clock) +
- muldiv64(s->period / c, get_ticks_per_sec(), 32768);
+ int64_t next_clock = qemu_get_clock(rtc_clock) +
+ muldiv64(s->period / c, get_ticks_per_sec(), 32768);
qemu_mod_timer(s->coalesced_timer, next_clock);
}
}
/* compute 32 khz clock */
cur_clock = muldiv64(current_time, 32768, get_ticks_per_sec());
next_irq_clock = (cur_clock & ~(period - 1)) + period;
- s->next_periodic_time = muldiv64(next_irq_clock, get_ticks_per_sec(), 32768) + 1;
+ s->next_periodic_time =
+ muldiv64(next_irq_clock, get_ticks_per_sec(), 32768) + 1;
qemu_mod_timer(s->periodic_timer, s->next_periodic_time);
} else {
#ifdef TARGET_I386
/* UIP bit is read only */
s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
(s->cmos_data[RTC_REG_A] & REG_A_UIP);
- rtc_timer_update(s, qemu_get_clock(vm_clock));
+ rtc_timer_update(s, qemu_get_clock(rtc_clock));
break;
case RTC_REG_B:
if (data & REG_B_SET) {
}
}
s->cmos_data[RTC_REG_B] = data;
- rtc_timer_update(s, qemu_get_clock(vm_clock));
+ rtc_timer_update(s, qemu_get_clock(rtc_clock));
break;
case RTC_REG_C:
case RTC_REG_D:
rtc_set_date_from_host(s);
- s->periodic_timer = qemu_new_timer(vm_clock,
- rtc_periodic_timer, s);
+ s->periodic_timer = qemu_new_timer(rtc_clock, rtc_periodic_timer, s);
#ifdef TARGET_I386
if (rtc_td_hack)
- s->coalesced_timer = qemu_new_timer(vm_clock, rtc_coalesced_timer, s);
+ s->coalesced_timer =
+ qemu_new_timer(rtc_clock, rtc_coalesced_timer, s);
#endif
- s->second_timer = qemu_new_timer(vm_clock,
- rtc_update_second, s);
- s->second_timer2 = qemu_new_timer(vm_clock,
- rtc_update_second2, s);
+ s->second_timer = qemu_new_timer(rtc_clock, rtc_update_second, s);
+ s->second_timer2 = qemu_new_timer(rtc_clock, rtc_update_second2, s);
- s->next_second_time = qemu_get_clock(vm_clock) + (get_ticks_per_sec() * 99) / 100;
+ s->next_second_time =
+ qemu_get_clock(rtc_clock) + (get_ticks_per_sec() * 99) / 100;
qemu_mod_timer(s->second_timer2, s->next_second_time);
register_ioport_write(base, 2, 1, cmos_ioport_write, s);
s->base_year = base_year;
rtc_set_date_from_host(s);
- s->periodic_timer = qemu_new_timer(vm_clock,
- rtc_periodic_timer, s);
- s->second_timer = qemu_new_timer(vm_clock,
- rtc_update_second, s);
- s->second_timer2 = qemu_new_timer(vm_clock,
- rtc_update_second2, s);
+ s->periodic_timer = qemu_new_timer(rtc_clock, rtc_periodic_timer, s);
+ s->second_timer = qemu_new_timer(rtc_clock, rtc_update_second, s);
+ s->second_timer2 = qemu_new_timer(rtc_clock, rtc_update_second2, s);
- s->next_second_time = qemu_get_clock(vm_clock) + (get_ticks_per_sec() * 99) / 100;
+ s->next_second_time =
+ qemu_get_clock(rtc_clock) + (get_ticks_per_sec() * 99) / 100;
qemu_mod_timer(s->second_timer2, s->next_second_time);
io_memory = cpu_register_io_memory(rtc_mm_read, rtc_mm_write, s);
#ifdef TARGET_I386
DEF("rtc", HAS_ARG, QEMU_OPTION_rtc, \
- "-rtc [base=utc|localtime|date][,driftfix=none|slew]\n" \
- " set the RTC base, enable drift fix for clock ticks\n")
+ "-rtc [base=utc|localtime|date][,clock=host|vm][,driftfix=none|slew]\n" \
+ " set the RTC base and clock, enable drift fix for clock ticks\n")
#else
DEF("rtc", HAS_ARG, QEMU_OPTION_rtc, \
- "-rtc [base=utc|localtime|date]\n" \
+ "-rtc [base=utc|localtime|date][,clock=host|vm]\n" \
" set the RTC base and clock\n")
#endif
STEXI
-@item -rtc [base=utc|localtime|@var{date}][,driftfix=none|slew]
+@item -rtc [base=utc|localtime|@var{date}][,clock=host|vm][,driftfix=none|slew]
Specify @option{base} as @code{utc} or @code{localtime} to let the RTC start at the current
UTC or local time, respectively. @code{localtime} is required for correct date in
MS-DOS or Windows. To start at a specific point in time, provide @var{date} in the
format @code{2006-06-17T16:01:21} or @code{2006-06-17}. The default base is UTC.
+By default the RTC is driven by the host system time. This allows to use the
+RTC as accurate reference clock inside the guest, specifically if the host
+time is smoothly following an accurate external reference clock, e.g. via NTP.
+If you want to isolate the guest time from the host, even prevent it from
+progressing during suspension, you can set @option{clock} to @code{vm} instead.
+
Enable @option{driftfix} (i386 targets only) if you experience time drift problems,
specifically with Windows' ACPI HAL. This option will try to figure out how
many timer interrupts were not processed by the Windows guest and will
int autostart;
static int rtc_utc = 1;
static int rtc_date_offset = -1; /* -1 means no change */
+QEMUClock *rtc_clock;
int vga_interface_type = VGA_CIRRUS;
#ifdef TARGET_SPARC
int graphic_width = 1024;
rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME);
vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL);
host_clock = qemu_new_clock(QEMU_CLOCK_HOST);
+
+ rtc_clock = host_clock;
}
/* save a timer */
configure_rtc_date_offset(value, 0);
}
}
+ value = qemu_opt_get(opts, "clock");
+ if (value) {
+ if (!strcmp(value, "host")) {
+ rtc_clock = host_clock;
+ } else if (!strcmp(value, "vm")) {
+ rtc_clock = vm_clock;
+ } else {
+ fprintf(stderr, "qemu: invalid option value '%s'\n", value);
+ exit(1);
+ }
+ }
#ifdef CONFIG_TARGET_I386
value = qemu_opt_get(opts, "driftfix");
if (value) {
CPUState *env;
int show_vnc_port = 0;
+ init_clocks();
+
qemu_errors_to_file(stderr);
qemu_cache_utils_init(envp);
setvbuf(stdout, NULL, _IOLBF, 0);
#endif
- init_clocks();
if (init_timer_alarm() < 0) {
fprintf(stderr, "could not initialize alarm timer\n");
exit(1);