diff options
-rw-r--r-- | qemu-config.c | 17 | ||||
-rw-r--r-- | qemu-config.h | 1 | ||||
-rw-r--r-- | qemu-options.hx | 47 | ||||
-rw-r--r-- | vl.c | 111 |
4 files changed, 119 insertions, 57 deletions
diff --git a/qemu-config.c b/qemu-config.c index 555c7ba091..3dce91d80e 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 13b0f19304..4ae7b74fe1 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 d3aa55b635..586474e39b 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, \ @@ -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); |