aboutsummaryrefslogtreecommitdiff
path: root/vl.c
diff options
context:
space:
mode:
Diffstat (limited to 'vl.c')
-rw-r--r--vl.c112
1 files changed, 73 insertions, 39 deletions
diff --git a/vl.c b/vl.c
index ac3ed17..9c34522 100644
--- a/vl.c
+++ b/vl.c
@@ -147,8 +147,15 @@ bool enable_cpu_pm = false;
int nb_nics;
NICInfo nd_table[MAX_NICS];
int autostart;
-static int rtc_utc = 1;
-static int rtc_date_offset = -1; /* -1 means no change */
+static enum {
+ RTC_BASE_UTC,
+ RTC_BASE_LOCALTIME,
+ RTC_BASE_DATETIME,
+} rtc_base_type = RTC_BASE_UTC;
+static time_t rtc_ref_start_datetime;
+static int rtc_realtime_clock_offset; /* used only with QEMU_CLOCK_REALTIME */
+static int rtc_host_datetime_offset = -1; /* valid & used only with
+ RTC_BASE_DATETIME */
QEMUClockType rtc_clock;
int vga_interface_type = VGA_NONE;
static DisplayOptions dpy;
@@ -242,6 +249,7 @@ static struct {
static QemuOptsList qemu_rtc_opts = {
.name = "rtc",
.head = QTAILQ_HEAD_INITIALIZER(qemu_rtc_opts.head),
+ .merge_lists = true,
.desc = {
{
.name = "base",
@@ -780,28 +788,42 @@ void qemu_system_vmstop_request(RunState state)
}
/***********************************************************/
-/* real time host monotonic timer */
-
-static time_t qemu_time(void)
+/* RTC reference time/date access */
+static time_t qemu_ref_timedate(QEMUClockType clock)
{
- return qemu_clock_get_ms(QEMU_CLOCK_HOST) / 1000;
+ time_t value = qemu_clock_get_ms(clock) / 1000;
+ switch (clock) {
+ case QEMU_CLOCK_REALTIME:
+ value -= rtc_realtime_clock_offset;
+ /* no break */
+ case QEMU_CLOCK_VIRTUAL:
+ value += rtc_ref_start_datetime;
+ break;
+ case QEMU_CLOCK_HOST:
+ if (rtc_base_type == RTC_BASE_DATETIME) {
+ value -= rtc_host_datetime_offset;
+ }
+ break;
+ default:
+ assert(0);
+ }
+ return value;
}
-/***********************************************************/
-/* host time/date access */
void qemu_get_timedate(struct tm *tm, int offset)
{
- time_t ti = qemu_time();
+ time_t ti = qemu_ref_timedate(rtc_clock);
ti += offset;
- if (rtc_date_offset == -1) {
- if (rtc_utc)
- gmtime_r(&ti, tm);
- else
- localtime_r(&ti, tm);
- } else {
- ti -= rtc_date_offset;
+
+ switch (rtc_base_type) {
+ case RTC_BASE_DATETIME:
+ case RTC_BASE_UTC:
gmtime_r(&ti, tm);
+ break;
+ case RTC_BASE_LOCALTIME:
+ localtime_r(&ti, tm);
+ break;
}
}
@@ -809,23 +831,28 @@ int qemu_timedate_diff(struct tm *tm)
{
time_t seconds;
- if (rtc_date_offset == -1)
- if (rtc_utc)
- seconds = mktimegm(tm);
- else {
- struct tm tmp = *tm;
- tmp.tm_isdst = -1; /* use timezone to figure it out */
- seconds = mktime(&tmp);
- }
- else
- seconds = mktimegm(tm) + rtc_date_offset;
-
- return seconds - qemu_time();
+ switch (rtc_base_type) {
+ case RTC_BASE_DATETIME:
+ case RTC_BASE_UTC:
+ seconds = mktimegm(tm);
+ break;
+ case RTC_BASE_LOCALTIME:
+ {
+ struct tm tmp = *tm;
+ tmp.tm_isdst = -1; /* use timezone to figure it out */
+ seconds = mktime(&tmp);
+ break;
+ }
+ default:
+ abort();
+ }
+
+ return seconds - qemu_ref_timedate(QEMU_CLOCK_HOST);
}
-static void configure_rtc_date_offset(const char *startdate)
+static void configure_rtc_base_datetime(const char *startdate)
{
- time_t rtc_start_date;
+ time_t rtc_start_datetime;
struct tm tm;
if (sscanf(startdate, "%d-%d-%dT%d:%d:%d", &tm.tm_year, &tm.tm_mon,
@@ -841,33 +868,40 @@ static void configure_rtc_date_offset(const char *startdate)
}
tm.tm_year -= 1900;
tm.tm_mon--;
- rtc_start_date = mktimegm(&tm);
- if (rtc_start_date == -1) {
+ rtc_start_datetime = mktimegm(&tm);
+ if (rtc_start_datetime == -1) {
date_fail:
- error_report("invalid date format");
+ error_report("invalid datetime format");
error_printf("valid formats: "
"'2006-06-17T16:01:21' or '2006-06-17'\n");
exit(1);
}
- rtc_date_offset = qemu_time() - rtc_start_date;
+ rtc_host_datetime_offset = rtc_ref_start_datetime - rtc_start_datetime;
+ rtc_ref_start_datetime = rtc_start_datetime;
}
static void configure_rtc(QemuOpts *opts)
{
const char *value;
+ /* Set defaults */
+ rtc_clock = QEMU_CLOCK_HOST;
+ rtc_ref_start_datetime = qemu_clock_get_ms(QEMU_CLOCK_HOST) / 1000;
+ rtc_realtime_clock_offset = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) / 1000;
+
value = qemu_opt_get(opts, "base");
if (value) {
if (!strcmp(value, "utc")) {
- rtc_utc = 1;
+ rtc_base_type = RTC_BASE_UTC;
} else if (!strcmp(value, "localtime")) {
Error *blocker = NULL;
- rtc_utc = 0;
+ rtc_base_type = RTC_BASE_LOCALTIME;
error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED,
"-rtc base=localtime");
replay_add_blocker(blocker);
} else {
- configure_rtc_date_offset(value);
+ rtc_base_type = RTC_BASE_DATETIME;
+ configure_rtc_base_datetime(value);
}
}
value = qemu_opt_get(opts, "clock");
@@ -3017,7 +3051,6 @@ int main(int argc, char **argv, char **envp)
error_reportf_err(err, "cannot initialize crypto: ");
exit(1);
}
- rtc_clock = QEMU_CLOCK_HOST;
QLIST_INIT (&vm_change_state_head);
os_setup_early_signal_handling();
@@ -3737,7 +3770,6 @@ int main(int argc, char **argv, char **envp)
if (!opts) {
exit(1);
}
- configure_rtc(opts);
break;
case QEMU_OPTION_tb_size:
#ifndef CONFIG_TCG
@@ -3955,6 +3987,8 @@ int main(int argc, char **argv, char **envp)
exit(EXIT_FAILURE);
}
+ configure_rtc(qemu_find_opts_singleton("rtc"));
+
machine_class = select_machine();
set_memory_options(&ram_slots, &maxram_size, machine_class);