* [Qemu-devel] [PATCH v3 4/5] Refactor RTC command line switches
2009-09-15 11:36 [Qemu-devel] [PATCH v3 0/5] Improve PC RTC emulation Jan Kiszka
@ 2009-09-15 11:36 ` Jan Kiszka
2009-10-06 10:32 ` Mark McLoughlin
2009-09-15 11:36 ` [Qemu-devel] [PATCH v3 5/5] Enable host-clock-based RTC Jan Kiszka
` (4 subsequent siblings)
5 siblings, 1 reply; 10+ messages in thread
From: Jan Kiszka @ 2009-09-15 11:36 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Blue Swirl, Glauber Costa, Dor Laor, qemu-devel
Deprecate -localtime, -setdate and -rtc-td-hack in favor of a new
unified command line switch:
-rtc [base=utc|localtime|date][,driftfix=none|slew]
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
qemu-config.c | 17 ++++++++
qemu-config.h | 1
qemu-options.hx | 47 ++++++++++++-----------
vl.c | 111 ++++++++++++++++++++++++++++++++++++++-----------------
4 files changed, 119 insertions(+), 57 deletions(-)
diff --git a/qemu-config.c b/qemu-config.c
index 39bf6a9..45a3e09 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -151,6 +151,23 @@ QemuOptsList qemu_device_opts = {
},
};
+QemuOptsList qemu_rtc_opts = {
+ .name = "rtc",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_rtc_opts.head),
+ .desc = {
+ {
+ .name = "base",
+ .type = QEMU_OPT_STRING,
+#ifdef TARGET_I386
+ },{
+ .name = "driftfix",
+ .type = QEMU_OPT_STRING,
+#endif
+ },
+ { /* end if list */ }
+ },
+};
+
static QemuOptsList *lists[] = {
&qemu_drive_opts,
&qemu_chardev_opts,
diff --git a/qemu-config.h b/qemu-config.h
index 13b0f19..4ae7b74 100644
--- a/qemu-config.h
+++ b/qemu-config.h
@@ -4,6 +4,7 @@
extern QemuOptsList qemu_drive_opts;
extern QemuOptsList qemu_chardev_opts;
extern QemuOptsList qemu_device_opts;
+extern QemuOptsList qemu_rtc_opts;
int qemu_set_option(const char *str);
diff --git a/qemu-options.hx b/qemu-options.hx
index d3aa55b..586474e 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -681,15 +681,9 @@ slows down the IDE transfers).
ETEXI
#ifdef TARGET_I386
-DEF("rtc-td-hack", 0, QEMU_OPTION_rtc_td_hack,
- "-rtc-td-hack use it to fix time drift in Windows ACPI HAL\n")
+HXCOMM Deprecated by -rtc
+DEF("rtc-td-hack", 0, QEMU_OPTION_rtc_td_hack, "")
#endif
-STEXI
-@item -rtc-td-hack
-Use it if you experience time drift problem 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.
-ETEXI
#ifdef TARGET_I386
DEF("no-fd-bootchk", 0, QEMU_OPTION_no_fd_bootchk,
@@ -1500,23 +1494,32 @@ Force the use of the given methods for timer alarm. To see what timers
are available use -clock ?.
ETEXI
-DEF("localtime", 0, QEMU_OPTION_localtime, \
- "-localtime set the real time clock to local time [default=utc]\n")
-STEXI
-@item -localtime
-Set the real time clock to local time (the default is to UTC
-time). This option is needed to have correct date in MS-DOS or
-Windows.
-ETEXI
+HXCOMM Options deprecated by -rtc
+DEF("localtime", 0, QEMU_OPTION_localtime, "")
+DEF("startdate", HAS_ARG, QEMU_OPTION_startdate, "")
+
+#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")
+#else
+DEF("rtc", HAS_ARG, QEMU_OPTION_rtc, \
+ "-rtc [base=utc|localtime|date]\n" \
+ " set the RTC base and clock\n")
+#endif
-DEF("startdate", HAS_ARG, QEMU_OPTION_startdate, \
- "-startdate select initial date of the clock\n")
STEXI
-@item -startdate @var{date}
-Set the initial date of the real time clock. Valid formats for
-@var{date} are: @code{now} or @code{2006-06-17T16:01:21} or
-@code{2006-06-17}. The default value is @code{now}.
+@item -rtc [base=utc|localtime|@var{date}][,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.
+
+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
+re-inject them.
ETEXI
DEF("icount", HAS_ARG, QEMU_OPTION_icount, \
diff --git a/vl.c b/vl.c
index 88113e6..0594ee8 100644
--- a/vl.c
+++ b/vl.c
@@ -1577,6 +1577,74 @@ int qemu_timedate_diff(struct tm *tm)
return seconds - time(NULL);
}
+static void configure_rtc_date_offset(const char *startdate, int legacy)
+{
+ time_t rtc_start_date;
+ struct tm tm;
+
+ if (!strcmp(startdate, "now") && legacy) {
+ rtc_date_offset = -1;
+ } else {
+ if (sscanf(startdate, "%d-%d-%dT%d:%d:%d",
+ &tm.tm_year,
+ &tm.tm_mon,
+ &tm.tm_mday,
+ &tm.tm_hour,
+ &tm.tm_min,
+ &tm.tm_sec) == 6) {
+ /* OK */
+ } else if (sscanf(startdate, "%d-%d-%d",
+ &tm.tm_year,
+ &tm.tm_mon,
+ &tm.tm_mday) == 3) {
+ tm.tm_hour = 0;
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
+ } else {
+ goto date_fail;
+ }
+ tm.tm_year -= 1900;
+ tm.tm_mon--;
+ rtc_start_date = mktimegm(&tm);
+ if (rtc_start_date == -1) {
+ date_fail:
+ fprintf(stderr, "Invalid date format. Valid formats are:\n"
+ "'2006-06-17T16:01:21' or '2006-06-17'\n");
+ exit(1);
+ }
+ rtc_date_offset = time(NULL) - rtc_start_date;
+ }
+}
+
+static void configure_rtc(QemuOpts *opts)
+{
+ const char *value;
+
+ value = qemu_opt_get(opts, "base");
+ if (value) {
+ if (!strcmp(value, "utc")) {
+ rtc_utc = 1;
+ } else if (!strcmp(value, "localtime")) {
+ rtc_utc = 0;
+ } else {
+ configure_rtc_date_offset(value, 0);
+ }
+ }
+#ifdef CONFIG_TARGET_I386
+ value = qemu_opt_get(opts, "driftfix");
+ if (value) {
+ if (!strcmp(buf, "slew")) {
+ rtc_td_hack = 1;
+ } else if (!strcmp(buf, "none")) {
+ rtc_td_hack = 0;
+ } else {
+ fprintf(stderr, "qemu: invalid option value '%s'\n", value);
+ exit(1);
+ }
+ }
+#endif
+}
+
#ifdef _WIN32
static void socket_cleanup(void)
{
@@ -5368,42 +5436,15 @@ int main(int argc, char **argv, char **envp)
configure_alarms(optarg);
break;
case QEMU_OPTION_startdate:
- {
- struct tm tm;
- time_t rtc_start_date;
- if (!strcmp(optarg, "now")) {
- rtc_date_offset = -1;
- } else {
- if (sscanf(optarg, "%d-%d-%dT%d:%d:%d",
- &tm.tm_year,
- &tm.tm_mon,
- &tm.tm_mday,
- &tm.tm_hour,
- &tm.tm_min,
- &tm.tm_sec) == 6) {
- /* OK */
- } else if (sscanf(optarg, "%d-%d-%d",
- &tm.tm_year,
- &tm.tm_mon,
- &tm.tm_mday) == 3) {
- tm.tm_hour = 0;
- tm.tm_min = 0;
- tm.tm_sec = 0;
- } else {
- goto date_fail;
- }
- tm.tm_year -= 1900;
- tm.tm_mon--;
- rtc_start_date = mktimegm(&tm);
- if (rtc_start_date == -1) {
- date_fail:
- fprintf(stderr, "Invalid date format. Valid format are:\n"
- "'now' or '2006-06-17T16:01:21' or '2006-06-17'\n");
- exit(1);
- }
- rtc_date_offset = time(NULL) - rtc_start_date;
- }
+ configure_rtc_date_offset(optarg, 1);
+ break;
+ case QEMU_OPTION_rtc:
+ opts = qemu_opts_parse(&qemu_rtc_opts, optarg, NULL);
+ if (!opts) {
+ fprintf(stderr, "parse error: %s\n", optarg);
+ exit(1);
}
+ configure_rtc(opts);
break;
case QEMU_OPTION_tb_size:
tb_size = strtol(optarg, NULL, 0);
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH v3 4/5] Refactor RTC command line switches
2009-09-15 11:36 ` [Qemu-devel] [PATCH v3 4/5] Refactor RTC command line switches Jan Kiszka
@ 2009-10-06 10:32 ` Mark McLoughlin
2009-10-06 10:59 ` [PATCH] Register rtc options for -set (was: [Qemu-devel] [PATCH v3 4/5] Refactor RTC command line switches) Jan Kiszka
0 siblings, 1 reply; 10+ messages in thread
From: Mark McLoughlin @ 2009-10-06 10:32 UTC (permalink / raw)
To: Jan Kiszka
Cc: Blue Swirl, Anthony Liguori, Dor Laor, Glauber Costa, qemu-devel
On Tue, 2009-09-15 at 13:36 +0200, Jan Kiszka wrote:
> Deprecate -localtime, -setdate and -rtc-td-hack in favor of a new
> unified command line switch:
>
> -rtc [base=utc|localtime|date][,driftfix=none|slew]
>
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> ---
>
> qemu-config.c | 17 ++++++++
> qemu-config.h | 1
> qemu-options.hx | 47 ++++++++++++-----------
> vl.c | 111 ++++++++++++++++++++++++++++++++++++++-----------------
> 4 files changed, 119 insertions(+), 57 deletions(-)
>
> diff --git a/qemu-config.c b/qemu-config.c
> index 39bf6a9..45a3e09 100644
> --- a/qemu-config.c
> +++ b/qemu-config.c
> @@ -151,6 +151,23 @@ QemuOptsList qemu_device_opts = {
> },
> };
>
> +QemuOptsList qemu_rtc_opts = {
> + .name = "rtc",
> + .head = QTAILQ_HEAD_INITIALIZER(qemu_rtc_opts.head),
> + .desc = {
> + {
> + .name = "base",
> + .type = QEMU_OPT_STRING,
> +#ifdef TARGET_I386
> + },{
> + .name = "driftfix",
> + .type = QEMU_OPT_STRING,
> +#endif
> + },
> + { /* end if list */ }
> + },
> +};
> +
> static QemuOptsList *lists[] = {
> &qemu_drive_opts,
> &qemu_chardev_opts,
Need to add qemu_rtc_opts to this list for -set
Cheers,
Mark.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH] Register rtc options for -set (was: [Qemu-devel] [PATCH v3 4/5] Refactor RTC command line switches)
2009-10-06 10:32 ` Mark McLoughlin
@ 2009-10-06 10:59 ` Jan Kiszka
0 siblings, 0 replies; 10+ messages in thread
From: Jan Kiszka @ 2009-10-06 10:59 UTC (permalink / raw)
To: Mark McLoughlin
Cc: Blue Swirl, Anthony Liguori, Dor Laor, Glauber Costa,
qemu-devel@nongnu.org
Mark McLoughlin wrote:
> On Tue, 2009-09-15 at 13:36 +0200, Jan Kiszka wrote:
>> Deprecate -localtime, -setdate and -rtc-td-hack in favor of a new
>> unified command line switch:
>>
>> -rtc [base=utc|localtime|date][,driftfix=none|slew]
>>
>> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
>> ---
>>
>> qemu-config.c | 17 ++++++++
>> qemu-config.h | 1
>> qemu-options.hx | 47 ++++++++++++-----------
>> vl.c | 111 ++++++++++++++++++++++++++++++++++++++-----------------
>> 4 files changed, 119 insertions(+), 57 deletions(-)
>>
>> diff --git a/qemu-config.c b/qemu-config.c
>> index 39bf6a9..45a3e09 100644
>> --- a/qemu-config.c
>> +++ b/qemu-config.c
>> @@ -151,6 +151,23 @@ QemuOptsList qemu_device_opts = {
>> },
>> };
>>
>> +QemuOptsList qemu_rtc_opts = {
>> + .name = "rtc",
>> + .head = QTAILQ_HEAD_INITIALIZER(qemu_rtc_opts.head),
>> + .desc = {
>> + {
>> + .name = "base",
>> + .type = QEMU_OPT_STRING,
>> +#ifdef TARGET_I386
>> + },{
>> + .name = "driftfix",
>> + .type = QEMU_OPT_STRING,
>> +#endif
>> + },
>> + { /* end if list */ }
>> + },
>> +};
>> +
>> static QemuOptsList *lists[] = {
>> &qemu_drive_opts,
>> &qemu_chardev_opts,
>
> Need to add qemu_rtc_opts to this list for -set
>
Ah, ok, thanks.
Jan
---------->
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
qemu-config.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/qemu-config.c b/qemu-config.c
index ca93dc7..2e396ae 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -176,6 +176,7 @@ static QemuOptsList *lists[] = {
&qemu_drive_opts,
&qemu_chardev_opts,
&qemu_device_opts,
+ &qemu_rtc_opts,
NULL,
};
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH v3 5/5] Enable host-clock-based RTC
2009-09-15 11:36 [Qemu-devel] [PATCH v3 0/5] Improve PC RTC emulation Jan Kiszka
2009-09-15 11:36 ` [Qemu-devel] [PATCH v3 4/5] Refactor RTC command line switches Jan Kiszka
@ 2009-09-15 11:36 ` Jan Kiszka
2009-09-15 11:36 ` [Qemu-devel] [PATCH v3 1/5] Rename QEMU_TIMER_* to QEMU_CLOCK_* Jan Kiszka
` (3 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Jan Kiszka @ 2009-09-15 11:36 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Blue Swirl, Glauber Costa, Dor Laor, qemu-devel
Switch RTC emulations to the new host_clock instead of vm_clock by
default. This has the advantage that the emulated RTC will follow
automatically the host time while it might be tuned via NTP. vm_clock
can still be selected by passing '-rtc clock=vm' on the command line.
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 but
only converts MC146818 for now.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
hw/mc146818rtc.c | 38 ++++++++++++++++++--------------------
qemu-config.c | 3 +++
qemu-options.hx | 14 ++++++++++----
sysemu.h | 2 ++
vl.c | 17 ++++++++++++++++-
5 files changed, 49 insertions(+), 25 deletions(-)
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 9d6a627..bec5687 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -108,8 +108,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, 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);
}
}
@@ -161,7 +161,8 @@ static void rtc_timer_update(RTCState *s, int64_t current_time)
/* 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
@@ -232,7 +233,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) {
@@ -246,7 +247,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:
@@ -605,18 +606,17 @@ static int rtc_initfn(ISADevice *dev)
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);
@@ -747,14 +747,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) + (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);
diff --git a/qemu-config.c b/qemu-config.c
index 45a3e09..35c3277 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -158,6 +158,9 @@ QemuOptsList qemu_rtc_opts = {
{
.name = "base",
.type = QEMU_OPT_STRING,
+ },{
+ .name = "clock",
+ .type = QEMU_OPT_STRING,
#ifdef TARGET_I386
},{
.name = "driftfix",
diff --git a/qemu-options.hx b/qemu-options.hx
index 586474e..f21e9f9 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1500,22 +1500,28 @@ DEF("startdate", HAS_ARG, QEMU_OPTION_startdate, "")
#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
diff --git a/sysemu.h b/sysemu.h
index 644a97d..c1dd1d3 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -5,6 +5,7 @@
#include "qemu-common.h"
#include "qemu-option.h"
#include "qemu-queue.h"
+#include "qemu-timer.h"
#include "qdict.h"
#ifdef _WIN32
@@ -134,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;
diff --git a/vl.c b/vl.c
index 0594ee8..c0c8332 100644
--- a/vl.c
+++ b/vl.c
@@ -193,6 +193,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;
@@ -1052,6 +1053,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 = host_clock;
}
/* save a timer */
@@ -1630,6 +1633,17 @@ static void configure_rtc(QemuOpts *opts)
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) {
@@ -4740,6 +4754,8 @@ int main(int argc, char **argv, char **envp)
CPUState *env;
int show_vnc_port = 0;
+ init_clocks();
+
qemu_errors_to_file(stderr);
qemu_cache_utils_init(envp);
@@ -5605,7 +5621,6 @@ int main(int argc, char **argv, char **envp)
setvbuf(stdout, NULL, _IOLBF, 0);
#endif
- init_clocks();
if (init_timer_alarm() < 0) {
fprintf(stderr, "could not initialize alarm timer\n");
exit(1);
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH v3 1/5] Rename QEMU_TIMER_* to QEMU_CLOCK_*
2009-09-15 11:36 [Qemu-devel] [PATCH v3 0/5] Improve PC RTC emulation Jan Kiszka
2009-09-15 11:36 ` [Qemu-devel] [PATCH v3 4/5] Refactor RTC command line switches Jan Kiszka
2009-09-15 11:36 ` [Qemu-devel] [PATCH v3 5/5] Enable host-clock-based RTC Jan Kiszka
@ 2009-09-15 11:36 ` Jan Kiszka
2009-09-15 11:36 ` [Qemu-devel] [PATCH v3 2/5] win32: Drop dead dyntick timer code Jan Kiszka
` (2 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Jan Kiszka @ 2009-09-15 11:36 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Blue Swirl, Glauber Costa, Dor Laor, qemu-devel
These constants select clocks, not timers. And init_timers initializes
clocks.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
vl.c | 42 +++++++++++++++++++++---------------------
1 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/vl.c b/vl.c
index 0e61333..bf77be5 100644
--- a/vl.c
+++ b/vl.c
@@ -673,8 +673,8 @@ void cpu_disable_ticks(void)
/***********************************************************/
/* timers */
-#define QEMU_TIMER_REALTIME 0
-#define QEMU_TIMER_VIRTUAL 1
+#define QEMU_CLOCK_REALTIME 0
+#define QEMU_CLOCK_VIRTUAL 1
struct QEMUClock {
int type;
@@ -1022,10 +1022,10 @@ static void qemu_run_timers(QEMUTimer **ptimer_head, int64_t current_time)
int64_t qemu_get_clock(QEMUClock *clock)
{
switch(clock->type) {
- case QEMU_TIMER_REALTIME:
+ case QEMU_CLOCK_REALTIME:
return get_clock() / 1000000;
default:
- case QEMU_TIMER_VIRTUAL:
+ case QEMU_CLOCK_VIRTUAL:
if (use_icount) {
return cpu_get_icount();
} else {
@@ -1034,11 +1034,11 @@ int64_t qemu_get_clock(QEMUClock *clock)
}
}
-static void init_timers(void)
+static void init_clocks(void)
{
init_get_clock();
- rt_clock = qemu_new_clock(QEMU_TIMER_REALTIME);
- vm_clock = qemu_new_clock(QEMU_TIMER_VIRTUAL);
+ rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME);
+ vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL);
}
/* save a timer */
@@ -1120,9 +1120,9 @@ static void host_alarm_handler(int host_signum)
#endif
if (alarm_has_dynticks(alarm_timer) ||
(!use_icount &&
- qemu_timer_expired(active_timers[QEMU_TIMER_VIRTUAL],
+ qemu_timer_expired(active_timers[QEMU_CLOCK_VIRTUAL],
qemu_get_clock(vm_clock))) ||
- qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME],
+ qemu_timer_expired(active_timers[QEMU_CLOCK_REALTIME],
qemu_get_clock(rt_clock))) {
qemu_event_increment();
if (alarm_timer) alarm_timer->flags |= ALARM_FLAG_EXPIRED;
@@ -1142,8 +1142,8 @@ static int64_t qemu_next_deadline(void)
{
int64_t delta;
- if (active_timers[QEMU_TIMER_VIRTUAL]) {
- delta = active_timers[QEMU_TIMER_VIRTUAL]->expire_time -
+ if (active_timers[QEMU_CLOCK_VIRTUAL]) {
+ delta = active_timers[QEMU_CLOCK_VIRTUAL]->expire_time -
qemu_get_clock(vm_clock);
} else {
/* To avoid problems with overflow limit this to 2^32. */
@@ -1167,8 +1167,8 @@ static uint64_t qemu_next_deadline_dyntick(void)
else
delta = (qemu_next_deadline() + 999) / 1000;
- if (active_timers[QEMU_TIMER_REALTIME]) {
- rtdelta = (active_timers[QEMU_TIMER_REALTIME]->expire_time -
+ if (active_timers[QEMU_CLOCK_REALTIME]) {
+ rtdelta = (active_timers[QEMU_CLOCK_REALTIME]->expire_time -
qemu_get_clock(rt_clock))*1000;
if (rtdelta < delta)
delta = rtdelta;
@@ -1350,8 +1350,8 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
int64_t nearest_delta_us = INT64_MAX;
int64_t current_us;
- if (!active_timers[QEMU_TIMER_REALTIME] &&
- !active_timers[QEMU_TIMER_VIRTUAL])
+ if (!active_timers[QEMU_CLOCK_REALTIME] &&
+ !active_timers[QEMU_CLOCK_VIRTUAL])
return;
nearest_delta_us = qemu_next_deadline_dyntick();
@@ -1466,8 +1466,8 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t)
struct qemu_alarm_win32 *data = t->priv;
uint64_t nearest_delta_us;
- if (!active_timers[QEMU_TIMER_REALTIME] &&
- !active_timers[QEMU_TIMER_VIRTUAL])
+ if (!active_timers[QEMU_CLOCK_REALTIME] &&
+ !active_timers[QEMU_CLOCK_VIRTUAL])
return;
nearest_delta_us = qemu_next_deadline_dyntick();
@@ -3898,12 +3898,12 @@ void main_loop_wait(int timeout)
/* vm time timers */
if (vm_running) {
if (!cur_cpu || likely(!(cur_cpu->singlestep_enabled & SSTEP_NOTIMER)))
- qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL],
- qemu_get_clock(vm_clock));
+ qemu_run_timers(&active_timers[QEMU_CLOCK_VIRTUAL],
+ qemu_get_clock(vm_clock));
}
/* real time timers */
- qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME],
+ qemu_run_timers(&active_timers[QEMU_CLOCK_REALTIME],
qemu_get_clock(rt_clock));
/* Check bottom-halves last in case any of the earlier events triggered
@@ -5544,7 +5544,7 @@ int main(int argc, char **argv, char **envp)
setvbuf(stdout, NULL, _IOLBF, 0);
#endif
- init_timers();
+ init_clocks();
if (init_timer_alarm() < 0) {
fprintf(stderr, "could not initialize alarm timer\n");
exit(1);
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH v3 2/5] win32: Drop dead dyntick timer code
2009-09-15 11:36 [Qemu-devel] [PATCH v3 0/5] Improve PC RTC emulation Jan Kiszka
` (2 preceding siblings ...)
2009-09-15 11:36 ` [Qemu-devel] [PATCH v3 1/5] Rename QEMU_TIMER_* to QEMU_CLOCK_* Jan Kiszka
@ 2009-09-15 11:36 ` Jan Kiszka
2009-09-15 11:36 ` [Qemu-devel] [PATCH v3 3/5] Introduce QEMU_CLOCK_HOST Jan Kiszka
2009-09-15 17:50 ` [Qemu-devel] Re: [PATCH v3 0/5] Improve PC RTC emulation Jamie Lokier
5 siblings, 0 replies; 10+ messages in thread
From: Jan Kiszka @ 2009-09-15 11:36 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Blue Swirl, Glauber Costa, Dor Laor, qemu-devel
nearest_delta_us is calculated but not used. Drop it.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
vl.c | 6 +-----
1 files changed, 1 insertions(+), 5 deletions(-)
diff --git a/vl.c b/vl.c
index bf77be5..f56fbce 100644
--- a/vl.c
+++ b/vl.c
@@ -1156,7 +1156,7 @@ static int64_t qemu_next_deadline(void)
return delta;
}
-#if defined(__linux__) || defined(_WIN32)
+#if defined(__linux__)
static uint64_t qemu_next_deadline_dyntick(void)
{
int64_t delta;
@@ -1464,15 +1464,11 @@ static void win32_stop_timer(struct qemu_alarm_timer *t)
static void win32_rearm_timer(struct qemu_alarm_timer *t)
{
struct qemu_alarm_win32 *data = t->priv;
- uint64_t nearest_delta_us;
if (!active_timers[QEMU_CLOCK_REALTIME] &&
!active_timers[QEMU_CLOCK_VIRTUAL])
return;
- nearest_delta_us = qemu_next_deadline_dyntick();
- nearest_delta_us /= 1000;
-
timeKillEvent(data->timerId);
data->timerId = timeSetEvent(1,
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH v3 3/5] Introduce QEMU_CLOCK_HOST
2009-09-15 11:36 [Qemu-devel] [PATCH v3 0/5] Improve PC RTC emulation Jan Kiszka
` (3 preceding siblings ...)
2009-09-15 11:36 ` [Qemu-devel] [PATCH v3 2/5] win32: Drop dead dyntick timer code Jan Kiszka
@ 2009-09-15 11:36 ` Jan Kiszka
2009-09-15 17:50 ` [Qemu-devel] Re: [PATCH v3 0/5] Improve PC RTC emulation Jamie Lokier
5 siblings, 0 replies; 10+ messages in thread
From: Jan Kiszka @ 2009-09-15 11:36 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Blue Swirl, Glauber Costa, Dor Laor, qemu-devel
Despite its name QEMU_CLOCK_REALTIME is (normally) not using
CLOCK_REALTIME / the host system time as base. In order to allow also
non-trivial RTC emulations (MC146818) to follow the host time instead of
the virtual guest time, introduce the new clock type QEMU_CLOCK_HOST. It
is unconditionally based on CLOCK_REALTIME, thus will follow system time
changes of the host.
The only limitation of its current implementation is that pending
host_clock timers may not fire early if the host time is pushed forward
beyond their expiry. So far no urgent need to overcome this limitation
was identified, so it's left as simple as it is (expiry on next alarm
timer tick).
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
qemu-timer.h | 7 +++++++
vl.c | 46 +++++++++++++++++++++++++++++++++++-----------
2 files changed, 42 insertions(+), 11 deletions(-)
diff --git a/qemu-timer.h b/qemu-timer.h
index e44c334..e7eaa04 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -17,6 +17,13 @@ extern QEMUClock *rt_clock;
precision clock, usually cpu cycles (use ticks_per_sec). */
extern QEMUClock *vm_clock;
+/* The host clock should be use for device models that emulate accurate
+ real time sources. It will continue to run when the virtual machine
+ is suspended, and it will reflect system time changes the host may
+ undergo (e.g. due to NTP). The host clock has the same precision as
+ the virtual clock. */
+extern QEMUClock *host_clock;
+
int64_t qemu_get_clock(QEMUClock *clock);
QEMUTimer *qemu_new_timer(QEMUClock *clock, QEMUTimerCB *cb, void *opaque);
diff --git a/vl.c b/vl.c
index f56fbce..88113e6 100644
--- a/vl.c
+++ b/vl.c
@@ -528,6 +528,14 @@ uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
/***********************************************************/
/* real time host monotonic timer */
+static int64_t get_clock_realtime(void)
+{
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+ return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000);
+}
+
#ifdef WIN32
static int64_t clock_freq;
@@ -582,9 +590,7 @@ static int64_t get_clock(void)
{
/* XXX: using gettimeofday leads to problems if the date
changes, so it should be avoided. */
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000);
+ return get_clock_realtime();
}
}
#endif
@@ -675,6 +681,7 @@ void cpu_disable_ticks(void)
#define QEMU_CLOCK_REALTIME 0
#define QEMU_CLOCK_VIRTUAL 1
+#define QEMU_CLOCK_HOST 2
struct QEMUClock {
int type;
@@ -901,10 +908,13 @@ next:
}
}
+#define QEMU_NUM_CLOCKS 3
+
QEMUClock *rt_clock;
QEMUClock *vm_clock;
+QEMUClock *host_clock;
-static QEMUTimer *active_timers[2];
+static QEMUTimer *active_timers[QEMU_NUM_CLOCKS];
static QEMUClock *qemu_new_clock(int type)
{
@@ -1031,6 +1041,8 @@ int64_t qemu_get_clock(QEMUClock *clock)
} else {
return cpu_get_clock();
}
+ case QEMU_CLOCK_HOST:
+ return get_clock_realtime();
}
}
@@ -1039,6 +1051,7 @@ static void init_clocks(void)
init_get_clock();
rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME);
vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL);
+ host_clock = qemu_new_clock(QEMU_CLOCK_HOST);
}
/* save a timer */
@@ -1123,7 +1136,9 @@ static void host_alarm_handler(int host_signum)
qemu_timer_expired(active_timers[QEMU_CLOCK_VIRTUAL],
qemu_get_clock(vm_clock))) ||
qemu_timer_expired(active_timers[QEMU_CLOCK_REALTIME],
- qemu_get_clock(rt_clock))) {
+ qemu_get_clock(rt_clock)) ||
+ qemu_timer_expired(active_timers[QEMU_CLOCK_HOST],
+ qemu_get_clock(host_clock))) {
qemu_event_increment();
if (alarm_timer) alarm_timer->flags |= ALARM_FLAG_EXPIRED;
@@ -1140,14 +1155,18 @@ static void host_alarm_handler(int host_signum)
static int64_t qemu_next_deadline(void)
{
- int64_t delta;
+ /* To avoid problems with overflow limit this to 2^32. */
+ int64_t delta = INT32_MAX;
if (active_timers[QEMU_CLOCK_VIRTUAL]) {
delta = active_timers[QEMU_CLOCK_VIRTUAL]->expire_time -
qemu_get_clock(vm_clock);
- } else {
- /* To avoid problems with overflow limit this to 2^32. */
- delta = INT32_MAX;
+ }
+ if (active_timers[QEMU_CLOCK_HOST]) {
+ int64_t hdelta = active_timers[QEMU_CLOCK_HOST]->expire_time -
+ qemu_get_clock(host_clock);
+ if (hdelta < delta)
+ delta = hdelta;
}
if (delta < 0)
@@ -1351,7 +1370,8 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
int64_t current_us;
if (!active_timers[QEMU_CLOCK_REALTIME] &&
- !active_timers[QEMU_CLOCK_VIRTUAL])
+ !active_timers[QEMU_CLOCK_VIRTUAL] &&
+ !active_timers[QEMU_CLOCK_HOST])
return;
nearest_delta_us = qemu_next_deadline_dyntick();
@@ -1466,7 +1486,8 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t)
struct qemu_alarm_win32 *data = t->priv;
if (!active_timers[QEMU_CLOCK_REALTIME] &&
- !active_timers[QEMU_CLOCK_VIRTUAL])
+ !active_timers[QEMU_CLOCK_VIRTUAL] &&
+ !active_timers[QEMU_CLOCK_HOST])
return;
timeKillEvent(data->timerId);
@@ -3902,6 +3923,9 @@ void main_loop_wait(int timeout)
qemu_run_timers(&active_timers[QEMU_CLOCK_REALTIME],
qemu_get_clock(rt_clock));
+ qemu_run_timers(&active_timers[QEMU_CLOCK_HOST],
+ qemu_get_clock(host_clock));
+
/* Check bottom-halves last in case any of the earlier events triggered
them. */
qemu_bh_poll();
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] Re: [PATCH v3 0/5] Improve PC RTC emulation
2009-09-15 11:36 [Qemu-devel] [PATCH v3 0/5] Improve PC RTC emulation Jan Kiszka
` (4 preceding siblings ...)
2009-09-15 11:36 ` [Qemu-devel] [PATCH v3 3/5] Introduce QEMU_CLOCK_HOST Jan Kiszka
@ 2009-09-15 17:50 ` Jamie Lokier
2009-09-15 18:51 ` Jan Kiszka
5 siblings, 1 reply; 10+ messages in thread
From: Jamie Lokier @ 2009-09-15 17:50 UTC (permalink / raw)
To: Jan Kiszka
Cc: Blue Swirl, Dor Laor, Anthony Liguori, Glauber Costa, qemu-devel
Jan Kiszka wrote:
> The aim of this series is to allow using the emulated PC RTC (MC146818)
> as a reliable time source for guests. This is particularly useful if the
> host runs NTP or has otherwise access to an accurate clock while the
> guest has not (no network, impossible to add an NTP implementation
> etc.).
I approve of these patches.
But still, how exactly is it useful, without NTP? Afaik, Linux does
not read the RTC except once at boot time, so it probably still needs
NTP or something like it to have reliable time. However, it does
_write_ the RTC every 11 minutes if running NTP - does that affect the
emulated behaviour? Or does the emulated RTC ignore writes?
Do any other OSes read the RTC more than once after boot?
-- Jamie
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Qemu-devel] Re: [PATCH v3 0/5] Improve PC RTC emulation
2009-09-15 17:50 ` [Qemu-devel] Re: [PATCH v3 0/5] Improve PC RTC emulation Jamie Lokier
@ 2009-09-15 18:51 ` Jan Kiszka
0 siblings, 0 replies; 10+ messages in thread
From: Jan Kiszka @ 2009-09-15 18:51 UTC (permalink / raw)
To: Jamie Lokier
Cc: Blue Swirl, Anthony Liguori, Dor Laor, Glauber Costa, qemu-devel
[-- Attachment #1: Type: text/plain, Size: 1462 bytes --]
Jamie Lokier wrote:
> Jan Kiszka wrote:
>> The aim of this series is to allow using the emulated PC RTC (MC146818)
>> as a reliable time source for guests. This is particularly useful if the
>> host runs NTP or has otherwise access to an accurate clock while the
>> guest has not (no network, impossible to add an NTP implementation
>> etc.).
>
> I approve of these patches.
>
> But still, how exactly is it useful, without NTP? Afaik, Linux does
> not read the RTC except once at boot time, so it probably still needs
> NTP or something like it to have reliable time. However, it does
> _write_ the RTC every 11 minutes if running NTP - does that affect the
> emulated behaviour? Or does the emulated RTC ignore writes?
Nope, it accepts writes and simply gain a larger offset to the host
clock this way. The same happens via -rtc base=localtime or
base=<some-date> BTW.
To make use of this new "accurate" RTC, Linux users should already be
fine with adjtimex --adjust. We are currently evaluating this approach.
The brute-force solution is still to run hwclock --hctosys in a loop.
>
> Do any other OSes read the RTC more than once after boot?
(At least our proprietary one does. :) )
Some Windows versions are known to use the RTC's periodic tick instead
of the PIC or APIC as time source. They will also benefit from the
potential better accuracy of the host-based RTC (which also affects its
IRQ events).
Jan
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread