@@ -107,8 +107,8 @@ static void rtc_coalesced_timer_update(RTCState *s)
} 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, ticks_per_sec, 32768);
+ int64_t next_clock = qemu_get_clock(rtc_clock) +
+ muldiv64(s->period / c, ticks_per_sec, 32768);
qemu_mod_timer(s->coalesced_timer, next_clock);
}
}
@@ -231,7 +231,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
/* 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) {
@@ -245,7 +245,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
}
}
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:
@@ -604,18 +604,17 @@ RTCState *rtc_init_sqw(int base, qemu_irq irq, qemu_irq sqw_irq, int base_year)
s->base_year = base_year;
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) + (ticks_per_sec * 99) / 100;
+ s->next_second_time =
+ qemu_get_clock(rtc_clock) + (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);
@@ -725,14 +724,12 @@ RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq,
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) + (ticks_per_sec * 99) / 100;
+ s->next_second_time =
+ qemu_get_clock(rtc_clock) + (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);
@@ -1498,22 +1498,28 @@ DEF("startdate", HAS_ARG, QEMU_OPTION_startdate, "")
#ifdef TARGET_I386
DEF("rtc", HAS_ARG, QEMU_OPTION_rtc, \
- "-rtc [base=utc|localtime|date][,drift-fix=on|off]\n" \
- " Set the RTC base, enable Windows time drift fix\n")
+ "-rtc [base=utc|localtime|date][,clock=vm|host][,drift-fix=on|off]\n" \
+ " Set the RTC base and clock, enable Windows time drift fix\n")
#else
DEF("rtc", HAS_ARG, QEMU_OPTION_rtc, \
- "-rtc [base=utc|localtime|date]\n" \
+ "-rtc [base=utc|localtime|date][,clock=vm|host]\n" \
" Set the RTC base and clock\n")
#endif
STEXI
-@item -rtc [base=utc|localtime|@var{date}][,drift-fix=on|off]
+@item -rtc [base=utc|localtime|@var{date}][,clock=vm|rt][,drift-fix=on|off]
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 a virtual clock (@code{vm}) which is not subject
+to host time adjustments and does not jump when the guest is supended and
+resumed or migrated. To use the host's system time instead, set @option{clock} to
+@code{host}. This is useful if the host time is smoothly following an accurate
+reference clock, e.g. via NTP, and wants to propagate this into the guest.
+
Enable @option{drift-fix} (i386 targets only) if you experience time drift problems
in Windows with ACPI HAL. This option will try to figure out how many timer
interrupts were not processed by the Windows guest and will re-inject them.
@@ -135,6 +135,7 @@ extern int no_quit;
extern int semihosting_enabled;
extern int old_param;
extern int boot_menu;
+extern QEMUClock *rtc_clock;
#define MAX_NODES 64
extern int nb_numa_nodes;
@@ -194,6 +194,7 @@ int vm_running;
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;
@@ -1051,6 +1052,8 @@ static void init_clocks(void)
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 = vm_clock;
}
/* save a timer */
@@ -1630,7 +1633,7 @@ static void configure_rtc_date_offset(const char *startdate, int legacy)
static void configure_rtc(const char *options)
{
static const char * const params[] = {
- "base",
+ "base", "clock",
#ifdef CONFIG_TARGET_I386
"td-hack",
#endif
@@ -1652,6 +1655,16 @@ static void configure_rtc(const char *options)
configure_rtc_date_offset(buf, 0);
}
}
+ if (get_param_value(buf, sizeof(buf), "clock", options)) {
+ if (!strcmp(buf, "vm")) {
+ rtc_clock = vm_clock;
+ } else if (!strcmp(buf, "host")) {
+ rtc_clock = host_clock;
+ } else {
+ fprintf(stderr, "qemu: invalid option value '%s'\n", buf);
+ exit(1);
+ }
+ }
#ifdef CONFIG_TARGET_I386
if (get_param_value(buf, sizeof(buf), "drift-hack", options)) {
if (!strcmp(buf, "on")) {
Allow RTC emulations to use the new host_clock instead of vm_clock. This has the advantage that the emulated RTC will follow automatically the host time while it might be tuned via NTP. Note that some RTC emulations (at least M48T59) already use the host time unconditionally while others (namely MC146818) do not. This patch introduces the required infrastructure for selecting the base clock and only converts MC146818 for now. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> --- hw/mc146818rtc.c | 35 ++++++++++++++++------------------- qemu-options.hx | 14 ++++++++++---- sysemu.h | 1 + vl.c | 15 ++++++++++++++- 4 files changed, 41 insertions(+), 24 deletions(-)