Real PC lets its user set the real-time-clock and store it on CMOS, which advances the clock even when the PC is offline.
This patch will allow doing the same with VM: - Before shutting a VM down, use the monitor's info timeoffset to see how much (in seconds) does the rtc differ from the host clock. - Store this offset somewhere. - Use it next time with -startdate now+offset. Dan. diff --git a/console.h b/console.h index 1ac74fa..3e1ac56 100644 --- a/console.h +++ b/console.h @@ -124,6 +124,8 @@ int vnc_display_open(DisplayState *ds, const char *display); int vnc_display_password(DisplayState *ds, const char *password); void do_info_vnc(void); +void do_info_timeoffset(void); + /* x_keymap.c */ extern uint8_t _translate_keycode(const int key); diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index c1d5956..246535a 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -397,16 +397,12 @@ static void rtc_set_date_from_host(RTCState *s) int val; /* set the CMOS date */ - if (rtc_start_date == -1) { - time(&ti); - if (rtc_utc) - tm = gmtime(&ti); - else - tm = localtime(&ti); - } else { - ti = rtc_start_date; + ti = rtc_start_date; + if (rtc_utc) tm = gmtime(&ti); - } + else + tm = localtime(&ti); + rtc_set_date(s, tm); val = to_bcd(s, (tm->tm_year / 100) + 19); @@ -603,3 +599,19 @@ RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq) register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s); return s; } + +int rtc_get_timeoffset(RTCState *s) +{ + time_t ti, rtc_ti; + + rtc_set_time(s); + + if (rtc_utc) + rtc_ti = timegm(&s->current_tm); + else + rtc_ti = mktime(&s->current_tm); + + time(&ti); + + return rtc_ti - ti; +} diff --git a/hw/pc.c b/hw/pc.c index 7049c44..bf60ca6 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -48,6 +48,12 @@ static PITState *pit; static IOAPICState *ioapic; static PCIDevice *i440fx_state; +void do_info_timeoffset(void) +{ + int rtc_get_timeoffset(RTCState *s); + term_printf("now%+d\n", rtc_get_timeoffset(rtc_state)); +} + static void ioport80_write(void *opaque, uint32_t addr, uint32_t data) { } diff --git a/monitor.c b/monitor.c index 4a9e8bb..bc2870e 100644 --- a/monitor.c +++ b/monitor.c @@ -1370,6 +1370,8 @@ static term_cmd_t info_cmds[] = { "", "show which guest mouse is receiving events" }, { "vnc", "", do_info_vnc, "", "show the vnc server status"}, + { "timeoffset", "", do_info_timeoffset, + "", "show how much the VM real time clock differ from host time" }, { "name", "", do_info_name, "", "show the current VM name" }, #if defined(TARGET_PPC) diff --git a/sysemu.h b/sysemu.h index d54f115..5a10518 100644 --- a/sysemu.h +++ b/sysemu.h @@ -72,7 +72,7 @@ void do_info_slirp(void); extern int ram_size; extern int bios_size; extern int rtc_utc; -extern int rtc_start_date; +extern time_t rtc_start_date; extern int cirrus_vga_enabled; extern int vmsvga_enabled; extern int graphic_width; diff --git a/vl.c b/vl.c index 6f83740..bed1402 100644 --- a/vl.c +++ b/vl.c @@ -183,7 +183,7 @@ int nb_nics; NICInfo nd_table[MAX_NICS]; int vm_running; int rtc_utc = 1; -int rtc_start_date = -1; /* -1 means now */ +time_t rtc_start_date; int cirrus_vga_enabled = 1; int vmsvga_enabled = 0; #ifdef TARGET_SPARC @@ -7709,6 +7709,8 @@ int main(int argc, char **argv) nb_nics = 0; /* default mac address of the first network interface */ + time(&rtc_start_date); /* now is the default */ + optind = 1; for(;;) { if (optind >= argc) @@ -8168,8 +8170,21 @@ int main(int argc, char **argv) case QEMU_OPTION_startdate: { struct tm tm; - if (!strcmp(optarg, "now")) { - rtc_start_date = -1; + char sign; + long timeoffset; + if (sscanf(optarg, "now%c%lu", &sign, &timeoffset) == 2) { + switch (sign) { + case '+': + rtc_start_date += timeoffset; + break; + case '-': + rtc_start_date -= timeoffset; + break; + default: + goto date_fail; + } + } else if (!strcmp(optarg, "now")) { + /* keep the default */ } else { if (sscanf(optarg, "%d-%d-%dT%d:%d:%d", &tm.tm_year,