qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] Handle -localtime and -startdate in one place


From: andrzej zaborowski
Subject: [Qemu-devel] [PATCH] Handle -localtime and -startdate in one place
Date: Sun, 10 Feb 2008 17:04:44 +0100

Here's a patch to change RTC hardware to use a global
qemu_get_timedate function instead of handling rtc_utc and
rtc_start_date so that these don't have to be global anymore.  The
means also that files in hw/ don't have to use time.h functions
(unless they want to).

hw/m48t59.c:alarm_cb was initialising tm_now in a wrong place, this
should be fixed now. I will apply if there are no objections.

diff --git a/hw/m48t59.c b/hw/m48t59.c
index 45c05a0..b781f50 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -53,7 +53,7 @@ struct m48t59_t {
     time_t   time_offset;
     time_t   stop_time;
     /* Alarm & watchdog */
-    time_t   alarm;
+    struct tm alarm;
     struct QEMUTimer *alrm_timer;
     struct QEMUTimer *wd_timer;
     /* NVRAM storage */
@@ -74,35 +74,10 @@ static inline uint8_t fromBCD (uint8_t BCD)
     return ((BCD >> 4) * 10) + (BCD & 0x0F);
 }

-/* RTC management helpers */
-static void get_time (m48t59_t *NVRAM, struct tm *tm)
-{
-    time_t t;
-
-    t = time(NULL) + NVRAM->time_offset;
-#ifdef _WIN32
-    memcpy(tm,localtime(&t),sizeof(*tm));
-#else
-    if (rtc_utc)
-        gmtime_r (&t, tm);
-    else
-        localtime_r (&t, tm) ;
-#endif
-}
-
-static void set_time (m48t59_t *NVRAM, struct tm *tm)
-{
-    time_t now, new_time;
-
-    new_time = mktime(tm);
-    now = time(NULL);
-    NVRAM->time_offset = new_time - now;
-}
-
 /* Alarm management */
 static void alarm_cb (void *opaque)
 {
-    struct tm tm, tm_now;
+    struct tm tm;
     uint64_t next_time;
     m48t59_t *NVRAM = opaque;

@@ -111,62 +86,62 @@ static void alarm_cb (void *opaque)
        (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
        (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
        (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
-       /* Repeat once a month */
-       get_time(NVRAM, &tm_now);
-       memcpy(&tm, &tm_now, sizeof(struct tm));
-       tm.tm_mon++;
-       if (tm.tm_mon == 13) {
-           tm.tm_mon = 1;
-           tm.tm_year++;
-       }
-       next_time = mktime(&tm);
+        /* Repeat once a month */
+        qemu_get_timedate(&tm, NVRAM->time_offset);
+        tm.tm_mon++;
+        if (tm.tm_mon == 13) {
+            tm.tm_mon = 1;
+            tm.tm_year++;
+        }
+        next_time = qemu_timedate_diff(&tm) - NVRAM->time_offset;
     } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
               (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
               (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
               (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
-       /* Repeat once a day */
-       next_time = 24 * 60 * 60 + mktime(&tm_now);
+        /* Repeat once a day */
+        next_time = 24 * 60 * 60;
     } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
               (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
               (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
               (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
-       /* Repeat once an hour */
-       next_time = 60 * 60 + mktime(&tm_now);
+        /* Repeat once an hour */
+        next_time = 60 * 60;
     } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
               (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
               (NVRAM->buffer[0x1FF3] & 0x80) != 0 &&
               (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
-       /* Repeat once a minute */
-       next_time = 60 + mktime(&tm_now);
+        /* Repeat once a minute */
+        next_time = 60;
     } else {
-       /* Repeat once a second */
-       next_time = 1 + mktime(&tm_now);
+        /* Repeat once a second */
+        next_time = 1;
     }
-    qemu_mod_timer(NVRAM->alrm_timer, next_time * 1000);
+    qemu_mod_timer(NVRAM->alrm_timer, qemu_get_clock(vm_clock) +
+                    next_time * 1000);
     qemu_set_irq(NVRAM->IRQ, 0);
 }

+static void set_alarm (m48t59_t *NVRAM)
+{
+    int diff;
+    if (NVRAM->alrm_timer != NULL) {
+        qemu_del_timer(NVRAM->alrm_timer);
+        diff = qemu_timedate_diff(&NVRAM->alarm) - NVRAM->time_offset;
+        if (diff > 0)
+            qemu_mod_timer(NVRAM->alrm_timer, diff * 1000);
+    }
+}

-static void get_alarm (m48t59_t *NVRAM, struct tm *tm)
+/* RTC management helpers */
+static inline void get_time (m48t59_t *NVRAM, struct tm *tm)
 {
-#ifdef _WIN32
-    memcpy(tm,localtime(&NVRAM->alarm),sizeof(*tm));
-#else
-    if (rtc_utc)
-        gmtime_r (&NVRAM->alarm, tm);
-    else
-        localtime_r (&NVRAM->alarm, tm);
-#endif
+    qemu_get_timedate(tm, NVRAM->time_offset);
 }

-static void set_alarm (m48t59_t *NVRAM, struct tm *tm)
+static void set_time (m48t59_t *NVRAM, struct tm *tm)
 {
-    NVRAM->alarm = mktime(tm);
-    if (NVRAM->alrm_timer != NULL) {
-        qemu_del_timer(NVRAM->alrm_timer);
-        if (NVRAM->alarm - time(NULL) > 0)
-            qemu_mod_timer(NVRAM->alrm_timer, NVRAM->alarm * 1000);
-    }
+    NVRAM->time_offset = qemu_timedate_diff(tm);
+    set_alarm(NVRAM);
 }

 /* Watchdog management */
@@ -229,40 +204,36 @@ void m48t59_write (void *opaque, uint32_t addr,
uint32_t val)
         /* alarm seconds */
         tmp = fromBCD(val & 0x7F);
         if (tmp >= 0 && tmp <= 59) {
-            get_alarm(NVRAM, &tm);
-            tm.tm_sec = tmp;
+            NVRAM->alarm.tm_sec = tmp;
             NVRAM->buffer[0x1FF2] = val;
-            set_alarm(NVRAM, &tm);
+            set_alarm(NVRAM);
         }
         break;
     case 0x1FF3:
         /* alarm minutes */
         tmp = fromBCD(val & 0x7F);
         if (tmp >= 0 && tmp <= 59) {
-            get_alarm(NVRAM, &tm);
-            tm.tm_min = tmp;
+            NVRAM->alarm.tm_min = tmp;
             NVRAM->buffer[0x1FF3] = val;
-            set_alarm(NVRAM, &tm);
+            set_alarm(NVRAM);
         }
         break;
     case 0x1FF4:
         /* alarm hours */
         tmp = fromBCD(val & 0x3F);
         if (tmp >= 0 && tmp <= 23) {
-            get_alarm(NVRAM, &tm);
-            tm.tm_hour = tmp;
+            NVRAM->alarm.tm_hour = tmp;
             NVRAM->buffer[0x1FF4] = val;
-            set_alarm(NVRAM, &tm);
+            set_alarm(NVRAM);
         }
         break;
     case 0x1FF5:
         /* alarm date */
         tmp = fromBCD(val & 0x1F);
         if (tmp != 0) {
-            get_alarm(NVRAM, &tm);
-            tm.tm_mday = tmp;
+            NVRAM->alarm.tm_mday = tmp;
             NVRAM->buffer[0x1FF5] = val;
-            set_alarm(NVRAM, &tm);
+            set_alarm(NVRAM);
         }
         break;
     case 0x1FF6:
@@ -288,7 +259,7 @@ void m48t59_write (void *opaque, uint32_t addr,
uint32_t val)
            tm.tm_sec = tmp;
            set_time(NVRAM, &tm);
        }
-       if ((val & 0x80) ^ (NVRAM->buffer[addr] & 0x80)) {
+        if ((val & 0x80) ^ (NVRAM->buffer[addr] & 0x80)) {
            if (val & 0x80) {
                NVRAM->stop_time = time(NULL);
            } else {
@@ -296,7 +267,7 @@ void m48t59_write (void *opaque, uint32_t addr,
uint32_t val)
                NVRAM->stop_time = 0;
            }
        }
-       NVRAM->buffer[addr] = val & 0x80;
+        NVRAM->buffer[addr] = val & 0x80;
         break;
     case 0x1FFA:
     case 0x07FA:
@@ -682,6 +653,7 @@ m48t59_t *m48t59_init (qemu_irq IRQ,
target_phys_addr_t mem_base,
         s->wd_timer = qemu_new_timer(vm_clock, &watchdog_cb, s);
     }
     s->lock = 0;
+    qemu_get_timedate(&s->alarm, 0);

     qemu_register_reset(m48t59_reset, s);
     save_base = mem_base ? mem_base : io_base;
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index e1e6427..30bb044 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -392,24 +392,14 @@ void rtc_set_date(RTCState *s, const struct tm *tm)

 static void rtc_set_date_from_host(RTCState *s)
 {
-    time_t ti;
-    struct tm *tm;
+    struct tm tm;
     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;
-        tm = gmtime(&ti);
-    }
-    rtc_set_date(s, tm);
+    qemu_get_timedate(&tm, 0);
+    rtc_set_date(s, &tm);

-    val = to_bcd(s, (tm->tm_year / 100) + 19);
+    val = to_bcd(s, (tm.tm_year / 100) + 19);
     rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
     rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
 }
diff --git a/hw/omap.c b/hw/omap.c
index ce63597..ee426dc 100644
--- a/hw/omap.c
+++ b/hw/omap.c
@@ -4345,7 +4345,6 @@ struct omap_rtc_s {
     int pm_am;
     int auto_comp;
     int round;
-    struct tm *(*convert)(const time_t *timep, struct tm *result);
     struct tm alarm_tm;
     time_t alarm_ti;

@@ -4668,7 +4667,7 @@ static void omap_rtc_tick(void *opaque)
         s->round = 0;
     }

-    localtime_r(&s->ti, &s->current_tm);
+    memcpy(&s->current_tm, localtime(&s->ti), sizeof(s->current_tm));

     if ((s->interrupts & 0x08) && s->ti == s->alarm_ti) {
         s->status |= 0x40;
@@ -4719,6 +4718,8 @@ static void omap_rtc_tick(void *opaque)

 static void omap_rtc_reset(struct omap_rtc_s *s)
 {
+    struct tm tm;
+
     s->interrupts = 0;
     s->comp_reg = 0;
     s->running = 0;
@@ -4729,8 +4730,8 @@ static void omap_rtc_reset(struct omap_rtc_s *s)
     memset(&s->alarm_tm, 0, sizeof(s->alarm_tm));
     s->alarm_tm.tm_mday = 0x01;
     s->status = 1 << 7;
-    time(&s->ti);
-    s->ti = mktime(s->convert(&s->ti, &s->current_tm));
+    qemu_get_timedate(&tm, 0);
+    s->ti = mktime(&tm);

     omap_rtc_alarm_update(s);
     omap_rtc_tick(s);
@@ -4747,7 +4748,6 @@ struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base,
     s->irq = irq[0];
     s->alarm = irq[1];
     s->clk = qemu_new_timer(rt_clock, omap_rtc_tick, s);
-    s->convert = rtc_utc ? gmtime_r : localtime_r;

     omap_rtc_reset(s);

diff --git a/hw/pl031.c b/hw/pl031.c
index 68e9005..bb5a69d 100644
--- a/hw/pl031.c
+++ b/hw/pl031.c
@@ -195,8 +195,7 @@ void pl031_init(uint32_t base, qemu_irq irq)
 {
     int iomemtype;
     pl031_state *s;
-    time_t ti;
-    struct tm *tm;
+    struct tm tm;

     s = qemu_mallocz(sizeof(pl031_state));
     if (!s)
@@ -211,12 +210,8 @@ void pl031_init(uint32_t base, qemu_irq irq)
     s->base = base;
     s->irq  = irq;
     /* ??? We assume vm_clock is zero at this point.  */
-    time(&ti);
-    if (rtc_utc)
-        tm = gmtime(&ti);
-    else
-        tm = localtime(&ti);
-    s->tick_offset = mktime(tm);
+    qemu_get_timedate(&tm, 0);
+    s->tick_offset = mktime(&tm);

     s->timer = qemu_new_timer(vm_clock, pl031_interrupt, s);
 }
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 14e3b95..0cb1672 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -1183,27 +1183,22 @@ static CPUWriteMemoryFunc *pxa2xx_rtc_writefn[] = {

 static void pxa2xx_rtc_init(struct pxa2xx_state_s *s)
 {
-    struct tm *tm;
-    time_t ti;
+    struct tm tm;
     int wom;

     s->rttr = 0x7fff;
     s->rtsr = 0;

-    time(&ti);
-    if (rtc_utc)
-        tm = gmtime(&ti);
-    else
-        tm = localtime(&ti);
-    wom = ((tm->tm_mday - 1) / 7) + 1;
-
-    s->last_rcnr = (uint32_t) ti;
-    s->last_rdcr = (wom << 20) | ((tm->tm_wday + 1) << 17) |
-            (tm->tm_hour << 12) | (tm->tm_min << 6) | tm->tm_sec;
-    s->last_rycr = ((tm->tm_year + 1900) << 9) |
-            ((tm->tm_mon + 1) << 5) | tm->tm_mday;
-    s->last_swcr = (tm->tm_hour << 19) |
-            (tm->tm_min << 13) | (tm->tm_sec << 7);
+    qemu_get_timedate(&tm, 0);
+    wom = ((tm.tm_mday - 1) / 7) + 1;
+
+    s->last_rcnr = (uint32_t) mktime(&tm);
+    s->last_rdcr = (wom << 20) | ((tm.tm_wday + 1) << 17) |
+            (tm.tm_hour << 12) | (tm.tm_min << 6) | tm.tm_sec;
+    s->last_rycr = ((tm.tm_year + 1900) << 9) |
+            ((tm.tm_mon + 1) << 5) | tm.tm_mday;
+    s->last_swcr = (tm.tm_hour << 19) |
+            (tm.tm_min << 13) | (tm.tm_sec << 7);
     s->last_rtcpicr = 0;
     s->last_hz = s->last_sw = s->last_pi = qemu_get_clock(rt_clock);

diff --git a/qemu-common.h b/qemu-common.h
index e8ea687..746dcc5 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -76,6 +76,9 @@ int qemu_bh_poll(void);

 uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c);

+void qemu_get_timedate(struct tm *tm, int offset);
+int qemu_timedate_diff(struct tm *tm);
+
 /* cutils.c */
 void pstrcpy(char *buf, int buf_size, const char *str);
 char *pstrcat(char *buf, int buf_size, const char *s);
diff --git a/sysemu.h b/sysemu.h
index 29377bf..296f179 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -71,8 +71,6 @@ void do_info_slirp(void);

 extern int ram_size;
 extern int bios_size;
-extern int rtc_utc;
-extern int 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 f99dd9b..59ba0a3 100644
--- a/vl.c
+++ b/vl.c
@@ -179,8 +179,8 @@ int pit_min_timer_count = 0;
 int nb_nics;
 NICInfo nd_table[MAX_NICS];
 int vm_running;
-int rtc_utc = 1;
-int rtc_start_date = -1; /* -1 means now */
+static int rtc_utc = 1;
+static int rtc_date_offset = -1; /* -1 means no change */
 int cirrus_vga_enabled = 1;
 int vmsvga_enabled = 0;
 #ifdef TARGET_SPARC
@@ -1564,6 +1564,43 @@ static void quit_timers(void)
 }

 /***********************************************************/
+/* host time access */
+void qemu_get_timedate(struct tm *tm, int offset)
+{
+    time_t ti;
+    struct tm *ret;
+
+    time(&ti);
+    ti += offset;
+    if (rtc_date_offset == -1) {
+        if (rtc_utc)
+            ret = gmtime(&ti);
+        else
+            ret = localtime(&ti);
+    } else {
+        ti -= rtc_date_offset;
+        ret = gmtime(&ti);
+    }
+
+    memcpy(tm, ret, sizeof(struct tm));
+}
+
+int qemu_timedate_diff(struct tm *tm)
+{
+    time_t seconds;
+
+    if (rtc_date_offset == -1)
+        if (rtc_utc)
+            seconds = mktimegm(tm);
+        else
+            seconds = mktime(tm);
+    else
+        seconds = mktimegm(tm) + rtc_date_offset;
+
+    return seconds - time(NULL);
+}
+
+/***********************************************************/
 /* character device */

 static void qemu_chr_event(CharDriverState *s, int event)
@@ -8684,8 +8721,9 @@ int main(int argc, char **argv)
             case QEMU_OPTION_startdate:
                 {
                     struct tm tm;
+                    time_t rtc_start_date;
                     if (!strcmp(optarg, "now")) {
-                        rtc_start_date = -1;
+                        rtc_date_offset = -1;
                     } else {
                         if (sscanf(optarg, "%d-%d-%dT%d:%d:%d",
                                &tm.tm_year,
@@ -8714,6 +8752,7 @@ int main(int argc, char **argv)
                                     "'now' or '2006-06-17T16:01:21'
or '2006-06-17'\n");
                             exit(1);
                         }
+                        rtc_date_offset = time(NULL) - rtc_start_date;
                     }
                 }
                 break;
-- 
Please do not print this email unless absolutely necessary. Spread
environmental awareness.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]