aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--qemu-config.c17
-rw-r--r--qemu-config.h1
-rw-r--r--qemu-options.hx47
-rw-r--r--vl.c111
4 files changed, 119 insertions, 57 deletions
diff --git a/qemu-config.c b/qemu-config.c
index 555c7ba09..3dce91d80 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 13b0f1930..4ae7b74fe 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 d3aa55b63..586474e39 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 bf592ec18..31f3ad250 100644
--- a/vl.c
+++ b/vl.c
@@ -1582,6 +1582,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)
{
@@ -5382,42 +5450,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);