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,


Reply via email to