These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / tests / rtc-test.c
1 /*
2  * QTest testcase for the MC146818 real-time clock
3  *
4  * Copyright IBM, Corp. 2012
5  *
6  * Authors:
7  *  Anthony Liguori   <aliguori@us.ibm.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10  * See the COPYING file in the top-level directory.
11  *
12  */
13
14 #include "qemu/osdep.h"
15 #include <glib.h>
16
17 #include "libqtest.h"
18 #include "hw/timer/mc146818rtc_regs.h"
19
20 static uint8_t base = 0x70;
21
22 static int bcd2dec(int value)
23 {
24     return (((value >> 4) & 0x0F) * 10) + (value & 0x0F);
25 }
26
27 static uint8_t cmos_read(uint8_t reg)
28 {
29     outb(base + 0, reg);
30     return inb(base + 1);
31 }
32
33 static void cmos_write(uint8_t reg, uint8_t val)
34 {
35     outb(base + 0, reg);
36     outb(base + 1, val);
37 }
38
39 static int tm_cmp(struct tm *lhs, struct tm *rhs)
40 {
41     time_t a, b;
42     struct tm d1, d2;
43
44     memcpy(&d1, lhs, sizeof(d1));
45     memcpy(&d2, rhs, sizeof(d2));
46
47     a = mktime(&d1);
48     b = mktime(&d2);
49
50     if (a < b) {
51         return -1;
52     } else if (a > b) {
53         return 1;
54     }
55
56     return 0;
57 }
58
59 #if 0
60 static void print_tm(struct tm *tm)
61 {
62     printf("%04d-%02d-%02d %02d:%02d:%02d\n",
63            tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
64            tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_gmtoff);
65 }
66 #endif
67
68 static void cmos_get_date_time(struct tm *date)
69 {
70     int base_year = 2000, hour_offset;
71     int sec, min, hour, mday, mon, year;
72     time_t ts;
73     struct tm dummy;
74
75     sec = cmos_read(RTC_SECONDS);
76     min = cmos_read(RTC_MINUTES);
77     hour = cmos_read(RTC_HOURS);
78     mday = cmos_read(RTC_DAY_OF_MONTH);
79     mon = cmos_read(RTC_MONTH);
80     year = cmos_read(RTC_YEAR);
81
82     if ((cmos_read(RTC_REG_B) & REG_B_DM) == 0) {
83         sec = bcd2dec(sec);
84         min = bcd2dec(min);
85         hour = bcd2dec(hour);
86         mday = bcd2dec(mday);
87         mon = bcd2dec(mon);
88         year = bcd2dec(year);
89         hour_offset = 80;
90     } else {
91         hour_offset = 0x80;
92     }
93
94     if ((cmos_read(0x0B) & REG_B_24H) == 0) {
95         if (hour >= hour_offset) {
96             hour -= hour_offset;
97             hour += 12;
98         }
99     }
100
101     ts = time(NULL);
102     localtime_r(&ts, &dummy);
103
104     date->tm_isdst = dummy.tm_isdst;
105     date->tm_sec = sec;
106     date->tm_min = min;
107     date->tm_hour = hour;
108     date->tm_mday = mday;
109     date->tm_mon = mon - 1;
110     date->tm_year = base_year + year - 1900;
111 #ifndef __sun__
112     date->tm_gmtoff = 0;
113 #endif
114
115     ts = mktime(date);
116 }
117
118 static void check_time(int wiggle)
119 {
120     struct tm start, date[4], end;
121     struct tm *datep;
122     time_t ts;
123
124     /*
125      * This check assumes a few things.  First, we cannot guarantee that we get
126      * a consistent reading from the wall clock because we may hit an edge of
127      * the clock while reading.  To work around this, we read four clock readings
128      * such that at least two of them should match.  We need to assume that one
129      * reading is corrupt so we need four readings to ensure that we have at
130      * least two consecutive identical readings
131      *
132      * It's also possible that we'll cross an edge reading the host clock so
133      * simply check to make sure that the clock reading is within the period of
134      * when we expect it to be.
135      */
136
137     ts = time(NULL);
138     gmtime_r(&ts, &start);
139
140     cmos_get_date_time(&date[0]);
141     cmos_get_date_time(&date[1]);
142     cmos_get_date_time(&date[2]);
143     cmos_get_date_time(&date[3]);
144
145     ts = time(NULL);
146     gmtime_r(&ts, &end);
147
148     if (tm_cmp(&date[0], &date[1]) == 0) {
149         datep = &date[0];
150     } else if (tm_cmp(&date[1], &date[2]) == 0) {
151         datep = &date[1];
152     } else if (tm_cmp(&date[2], &date[3]) == 0) {
153         datep = &date[2];
154     } else {
155         g_assert_not_reached();
156     }
157
158     if (!(tm_cmp(&start, datep) <= 0 && tm_cmp(datep, &end) <= 0)) {
159         long t, s;
160
161         start.tm_isdst = datep->tm_isdst;
162
163         t = (long)mktime(datep);
164         s = (long)mktime(&start);
165         if (t < s) {
166             g_test_message("RTC is %ld second(s) behind wall-clock\n", (s - t));
167         } else {
168             g_test_message("RTC is %ld second(s) ahead of wall-clock\n", (t - s));
169         }
170
171         g_assert_cmpint(ABS(t - s), <=, wiggle);
172     }
173 }
174
175 static int wiggle = 2;
176
177 static void set_year_20xx(void)
178 {
179     /* Set BCD mode */
180     cmos_write(RTC_REG_B, REG_B_24H);
181     cmos_write(RTC_REG_A, 0x76);
182     cmos_write(RTC_YEAR, 0x11);
183     cmos_write(RTC_CENTURY, 0x20);
184     cmos_write(RTC_MONTH, 0x02);
185     cmos_write(RTC_DAY_OF_MONTH, 0x02);
186     cmos_write(RTC_HOURS, 0x02);
187     cmos_write(RTC_MINUTES, 0x04);
188     cmos_write(RTC_SECONDS, 0x58);
189     cmos_write(RTC_REG_A, 0x26);
190
191     g_assert_cmpint(cmos_read(RTC_HOURS), ==, 0x02);
192     g_assert_cmpint(cmos_read(RTC_MINUTES), ==, 0x04);
193     g_assert_cmpint(cmos_read(RTC_SECONDS), >=, 0x58);
194     g_assert_cmpint(cmos_read(RTC_DAY_OF_MONTH), ==, 0x02);
195     g_assert_cmpint(cmos_read(RTC_MONTH), ==, 0x02);
196     g_assert_cmpint(cmos_read(RTC_YEAR), ==, 0x11);
197     g_assert_cmpint(cmos_read(RTC_CENTURY), ==, 0x20);
198
199     if (sizeof(time_t) == 4) {
200         return;
201     }
202
203     /* Set a date in 2080 to ensure there is no year-2038 overflow.  */
204     cmos_write(RTC_REG_A, 0x76);
205     cmos_write(RTC_YEAR, 0x80);
206     cmos_write(RTC_REG_A, 0x26);
207
208     g_assert_cmpint(cmos_read(RTC_HOURS), ==, 0x02);
209     g_assert_cmpint(cmos_read(RTC_MINUTES), ==, 0x04);
210     g_assert_cmpint(cmos_read(RTC_SECONDS), >=, 0x58);
211     g_assert_cmpint(cmos_read(RTC_DAY_OF_MONTH), ==, 0x02);
212     g_assert_cmpint(cmos_read(RTC_MONTH), ==, 0x02);
213     g_assert_cmpint(cmos_read(RTC_YEAR), ==, 0x80);
214     g_assert_cmpint(cmos_read(RTC_CENTURY), ==, 0x20);
215
216     cmos_write(RTC_REG_A, 0x76);
217     cmos_write(RTC_YEAR, 0x11);
218     cmos_write(RTC_REG_A, 0x26);
219
220     g_assert_cmpint(cmos_read(RTC_HOURS), ==, 0x02);
221     g_assert_cmpint(cmos_read(RTC_MINUTES), ==, 0x04);
222     g_assert_cmpint(cmos_read(RTC_SECONDS), >=, 0x58);
223     g_assert_cmpint(cmos_read(RTC_DAY_OF_MONTH), ==, 0x02);
224     g_assert_cmpint(cmos_read(RTC_MONTH), ==, 0x02);
225     g_assert_cmpint(cmos_read(RTC_YEAR), ==, 0x11);
226     g_assert_cmpint(cmos_read(RTC_CENTURY), ==, 0x20);
227 }
228
229 static void set_year_1980(void)
230 {
231     /* Set BCD mode */
232     cmos_write(RTC_REG_B, REG_B_24H);
233     cmos_write(RTC_REG_A, 0x76);
234     cmos_write(RTC_YEAR, 0x80);
235     cmos_write(RTC_CENTURY, 0x19);
236     cmos_write(RTC_MONTH, 0x02);
237     cmos_write(RTC_DAY_OF_MONTH, 0x02);
238     cmos_write(RTC_HOURS, 0x02);
239     cmos_write(RTC_MINUTES, 0x04);
240     cmos_write(RTC_SECONDS, 0x58);
241     cmos_write(RTC_REG_A, 0x26);
242
243     g_assert_cmpint(cmos_read(RTC_HOURS), ==, 0x02);
244     g_assert_cmpint(cmos_read(RTC_MINUTES), ==, 0x04);
245     g_assert_cmpint(cmos_read(RTC_SECONDS), >=, 0x58);
246     g_assert_cmpint(cmos_read(RTC_DAY_OF_MONTH), ==, 0x02);
247     g_assert_cmpint(cmos_read(RTC_MONTH), ==, 0x02);
248     g_assert_cmpint(cmos_read(RTC_YEAR), ==, 0x80);
249     g_assert_cmpint(cmos_read(RTC_CENTURY), ==, 0x19);
250 }
251
252 static void bcd_check_time(void)
253 {
254     /* Set BCD mode */
255     cmos_write(RTC_REG_B, REG_B_24H);
256     check_time(wiggle);
257 }
258
259 static void dec_check_time(void)
260 {
261     /* Set DEC mode */
262     cmos_write(RTC_REG_B, REG_B_24H | REG_B_DM);
263     check_time(wiggle);
264 }
265
266 static void alarm_time(void)
267 {
268     struct tm now;
269     time_t ts;
270     int i;
271
272     ts = time(NULL);
273     gmtime_r(&ts, &now);
274
275     /* set DEC mode */
276     cmos_write(RTC_REG_B, REG_B_24H | REG_B_DM);
277
278     g_assert(!get_irq(RTC_ISA_IRQ));
279     cmos_read(RTC_REG_C);
280
281     now.tm_sec = (now.tm_sec + 2) % 60;
282     cmos_write(RTC_SECONDS_ALARM, now.tm_sec);
283     cmos_write(RTC_MINUTES_ALARM, RTC_ALARM_DONT_CARE);
284     cmos_write(RTC_HOURS_ALARM, RTC_ALARM_DONT_CARE);
285     cmos_write(RTC_REG_B, cmos_read(RTC_REG_B) | REG_B_AIE);
286
287     for (i = 0; i < 2 + wiggle; i++) {
288         if (get_irq(RTC_ISA_IRQ)) {
289             break;
290         }
291
292         clock_step(1000000000);
293     }
294
295     g_assert(get_irq(RTC_ISA_IRQ));
296     g_assert((cmos_read(RTC_REG_C) & REG_C_AF) != 0);
297     g_assert(cmos_read(RTC_REG_C) == 0);
298 }
299
300 static void set_time(int mode, int h, int m, int s)
301 {
302     /* set BCD 12 hour mode */
303     cmos_write(RTC_REG_B, mode);
304
305     cmos_write(RTC_REG_A, 0x76);
306     cmos_write(RTC_HOURS, h);
307     cmos_write(RTC_MINUTES, m);
308     cmos_write(RTC_SECONDS, s);
309     cmos_write(RTC_REG_A, 0x26);
310 }
311
312 #define assert_time(h, m, s) \
313     do { \
314         g_assert_cmpint(cmos_read(RTC_HOURS), ==, h); \
315         g_assert_cmpint(cmos_read(RTC_MINUTES), ==, m); \
316         g_assert_cmpint(cmos_read(RTC_SECONDS), ==, s); \
317     } while(0)
318
319 static void basic_12h_bcd(void)
320 {
321     /* set BCD 12 hour mode */
322     set_time(0, 0x81, 0x59, 0x00);
323     clock_step(1000000000LL);
324     assert_time(0x81, 0x59, 0x01);
325     clock_step(59000000000LL);
326     assert_time(0x82, 0x00, 0x00);
327
328     /* test BCD wraparound */
329     set_time(0, 0x09, 0x59, 0x59);
330     clock_step(60000000000LL);
331     assert_time(0x10, 0x00, 0x59);
332
333     /* 12 AM -> 1 AM */
334     set_time(0, 0x12, 0x59, 0x59);
335     clock_step(1000000000LL);
336     assert_time(0x01, 0x00, 0x00);
337
338     /* 12 PM -> 1 PM */
339     set_time(0, 0x92, 0x59, 0x59);
340     clock_step(1000000000LL);
341     assert_time(0x81, 0x00, 0x00);
342
343     /* 11 AM -> 12 PM */
344     set_time(0, 0x11, 0x59, 0x59);
345     clock_step(1000000000LL);
346     assert_time(0x92, 0x00, 0x00);
347     /* TODO: test day wraparound */
348
349     /* 11 PM -> 12 AM */
350     set_time(0, 0x91, 0x59, 0x59);
351     clock_step(1000000000LL);
352     assert_time(0x12, 0x00, 0x00);
353     /* TODO: test day wraparound */
354 }
355
356 static void basic_12h_dec(void)
357 {
358     /* set decimal 12 hour mode */
359     set_time(REG_B_DM, 0x81, 59, 0);
360     clock_step(1000000000LL);
361     assert_time(0x81, 59, 1);
362     clock_step(59000000000LL);
363     assert_time(0x82, 0, 0);
364
365     /* 12 PM -> 1 PM */
366     set_time(REG_B_DM, 0x8c, 59, 59);
367     clock_step(1000000000LL);
368     assert_time(0x81, 0, 0);
369
370     /* 12 AM -> 1 AM */
371     set_time(REG_B_DM, 0x0c, 59, 59);
372     clock_step(1000000000LL);
373     assert_time(0x01, 0, 0);
374
375     /* 11 AM -> 12 PM */
376     set_time(REG_B_DM, 0x0b, 59, 59);
377     clock_step(1000000000LL);
378     assert_time(0x8c, 0, 0);
379
380     /* 11 PM -> 12 AM */
381     set_time(REG_B_DM, 0x8b, 59, 59);
382     clock_step(1000000000LL);
383     assert_time(0x0c, 0, 0);
384     /* TODO: test day wraparound */
385 }
386
387 static void basic_24h_bcd(void)
388 {
389     /* set BCD 24 hour mode */
390     set_time(REG_B_24H, 0x09, 0x59, 0x00);
391     clock_step(1000000000LL);
392     assert_time(0x09, 0x59, 0x01);
393     clock_step(59000000000LL);
394     assert_time(0x10, 0x00, 0x00);
395
396     /* test BCD wraparound */
397     set_time(REG_B_24H, 0x09, 0x59, 0x00);
398     clock_step(60000000000LL);
399     assert_time(0x10, 0x00, 0x00);
400
401     /* TODO: test day wraparound */
402     set_time(REG_B_24H, 0x23, 0x59, 0x00);
403     clock_step(60000000000LL);
404     assert_time(0x00, 0x00, 0x00);
405 }
406
407 static void basic_24h_dec(void)
408 {
409     /* set decimal 24 hour mode */
410     set_time(REG_B_24H | REG_B_DM, 9, 59, 0);
411     clock_step(1000000000LL);
412     assert_time(9, 59, 1);
413     clock_step(59000000000LL);
414     assert_time(10, 0, 0);
415
416     /* test BCD wraparound */
417     set_time(REG_B_24H | REG_B_DM, 9, 59, 0);
418     clock_step(60000000000LL);
419     assert_time(10, 0, 0);
420
421     /* TODO: test day wraparound */
422     set_time(REG_B_24H | REG_B_DM, 23, 59, 0);
423     clock_step(60000000000LL);
424     assert_time(0, 0, 0);
425 }
426
427 static void am_pm_alarm(void)
428 {
429     cmos_write(RTC_MINUTES_ALARM, 0xC0);
430     cmos_write(RTC_SECONDS_ALARM, 0xC0);
431
432     /* set BCD 12 hour mode */
433     cmos_write(RTC_REG_B, 0);
434
435     /* Set time and alarm hour.  */
436     cmos_write(RTC_REG_A, 0x76);
437     cmos_write(RTC_HOURS_ALARM, 0x82);
438     cmos_write(RTC_HOURS, 0x81);
439     cmos_write(RTC_MINUTES, 0x59);
440     cmos_write(RTC_SECONDS, 0x00);
441     cmos_read(RTC_REG_C);
442     cmos_write(RTC_REG_A, 0x26);
443
444     /* Check that alarm triggers when AM/PM is set.  */
445     clock_step(60000000000LL);
446     g_assert(cmos_read(RTC_HOURS) == 0x82);
447     g_assert((cmos_read(RTC_REG_C) & REG_C_AF) != 0);
448
449     /*
450      * Each of the following two tests takes over 60 seconds due to the time
451      * needed to report the PIT interrupts.  Unfortunately, our PIT device
452      * model keeps counting even when GATE=0, so we cannot simply disable
453      * it in main().
454      */
455     if (g_test_quick()) {
456         return;
457     }
458
459     /* set DEC 12 hour mode */
460     cmos_write(RTC_REG_B, REG_B_DM);
461
462     /* Set time and alarm hour.  */
463     cmos_write(RTC_REG_A, 0x76);
464     cmos_write(RTC_HOURS_ALARM, 0x82);
465     cmos_write(RTC_HOURS, 3);
466     cmos_write(RTC_MINUTES, 0);
467     cmos_write(RTC_SECONDS, 0);
468     cmos_read(RTC_REG_C);
469     cmos_write(RTC_REG_A, 0x26);
470
471     /* Check that alarm triggers.  */
472     clock_step(3600 * 11 * 1000000000LL);
473     g_assert(cmos_read(RTC_HOURS) == 0x82);
474     g_assert((cmos_read(RTC_REG_C) & REG_C_AF) != 0);
475
476     /* Same as above, with inverted HOURS and HOURS_ALARM.  */
477     cmos_write(RTC_REG_A, 0x76);
478     cmos_write(RTC_HOURS_ALARM, 2);
479     cmos_write(RTC_HOURS, 3);
480     cmos_write(RTC_MINUTES, 0);
481     cmos_write(RTC_SECONDS, 0);
482     cmos_read(RTC_REG_C);
483     cmos_write(RTC_REG_A, 0x26);
484
485     /* Check that alarm does not trigger if hours differ only by AM/PM.  */
486     clock_step(3600 * 11 * 1000000000LL);
487     g_assert(cmos_read(RTC_HOURS) == 0x82);
488     g_assert((cmos_read(RTC_REG_C) & REG_C_AF) == 0);
489 }
490
491 /* success if no crash or abort */
492 static void fuzz_registers(void)
493 {
494     unsigned int i;
495
496     for (i = 0; i < 1000; i++) {
497         uint8_t reg, val;
498
499         reg = (uint8_t)g_test_rand_int_range(0, 16);
500         val = (uint8_t)g_test_rand_int_range(0, 256);
501
502         cmos_write(reg, val);
503         cmos_read(reg);
504     }
505 }
506
507 static void register_b_set_flag(void)
508 {
509     /* Enable binary-coded decimal (BCD) mode and SET flag in Register B*/
510     cmos_write(RTC_REG_B, REG_B_24H | REG_B_SET);
511
512     cmos_write(RTC_REG_A, 0x76);
513     cmos_write(RTC_YEAR, 0x11);
514     cmos_write(RTC_CENTURY, 0x20);
515     cmos_write(RTC_MONTH, 0x02);
516     cmos_write(RTC_DAY_OF_MONTH, 0x02);
517     cmos_write(RTC_HOURS, 0x02);
518     cmos_write(RTC_MINUTES, 0x04);
519     cmos_write(RTC_SECONDS, 0x58);
520     cmos_write(RTC_REG_A, 0x26);
521
522     /* Since SET flag is still enabled, these are equality checks. */
523     g_assert_cmpint(cmos_read(RTC_HOURS), ==, 0x02);
524     g_assert_cmpint(cmos_read(RTC_MINUTES), ==, 0x04);
525     g_assert_cmpint(cmos_read(RTC_SECONDS), ==, 0x58);
526     g_assert_cmpint(cmos_read(RTC_DAY_OF_MONTH), ==, 0x02);
527     g_assert_cmpint(cmos_read(RTC_MONTH), ==, 0x02);
528     g_assert_cmpint(cmos_read(RTC_YEAR), ==, 0x11);
529     g_assert_cmpint(cmos_read(RTC_CENTURY), ==, 0x20);
530
531     /* Disable SET flag in Register B */
532     cmos_write(RTC_REG_B, cmos_read(RTC_REG_B) & ~REG_B_SET);
533
534     g_assert_cmpint(cmos_read(RTC_HOURS), ==, 0x02);
535     g_assert_cmpint(cmos_read(RTC_MINUTES), ==, 0x04);
536
537     /* Since SET flag is disabled, this is an inequality check.
538      * We (reasonably) assume that no (sexagesimal) overflow occurs. */
539     g_assert_cmpint(cmos_read(RTC_SECONDS), >=, 0x58);
540     g_assert_cmpint(cmos_read(RTC_DAY_OF_MONTH), ==, 0x02);
541     g_assert_cmpint(cmos_read(RTC_MONTH), ==, 0x02);
542     g_assert_cmpint(cmos_read(RTC_YEAR), ==, 0x11);
543     g_assert_cmpint(cmos_read(RTC_CENTURY), ==, 0x20);
544 }
545
546 int main(int argc, char **argv)
547 {
548     QTestState *s = NULL;
549     int ret;
550
551     g_test_init(&argc, &argv, NULL);
552
553     s = qtest_start("-rtc clock=vm");
554     qtest_irq_intercept_in(s, "ioapic");
555
556     qtest_add_func("/rtc/check-time/bcd", bcd_check_time);
557     qtest_add_func("/rtc/check-time/dec", dec_check_time);
558     qtest_add_func("/rtc/alarm/interrupt", alarm_time);
559     qtest_add_func("/rtc/alarm/am-pm", am_pm_alarm);
560     qtest_add_func("/rtc/basic/dec-24h", basic_24h_dec);
561     qtest_add_func("/rtc/basic/bcd-24h", basic_24h_bcd);
562     qtest_add_func("/rtc/basic/dec-12h", basic_12h_dec);
563     qtest_add_func("/rtc/basic/bcd-12h", basic_12h_bcd);
564     qtest_add_func("/rtc/set-year/20xx", set_year_20xx);
565     qtest_add_func("/rtc/set-year/1980", set_year_1980);
566     qtest_add_func("/rtc/misc/register_b_set_flag", register_b_set_flag);
567     qtest_add_func("/rtc/misc/fuzz-registers", fuzz_registers);
568     ret = g_test_run();
569
570     if (s) {
571         qtest_quit(s);
572     }
573
574     return ret;
575 }