]> Git Repo - qemu.git/blob - tests/rtc-test.c
tests/docker/Makefile.include: only force SID to NOCACHE if old
[qemu.git] / 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   <[email protected]>
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
16 #include "libqtest.h"
17 #include "qemu/timer.h"
18 #include "hw/timer/mc146818rtc_regs.h"
19
20 #define UIP_HOLD_LENGTH           (8 * NANOSECONDS_PER_SECOND / 32768)
21
22 static uint8_t base = 0x70;
23
24 static int bcd2dec(int value)
25 {
26     return (((value >> 4) & 0x0F) * 10) + (value & 0x0F);
27 }
28
29 static uint8_t cmos_read(uint8_t reg)
30 {
31     outb(base + 0, reg);
32     return inb(base + 1);
33 }
34
35 static void cmos_write(uint8_t reg, uint8_t val)
36 {
37     outb(base + 0, reg);
38     outb(base + 1, val);
39 }
40
41 static int tm_cmp(struct tm *lhs, struct tm *rhs)
42 {
43     time_t a, b;
44     struct tm d1, d2;
45
46     memcpy(&d1, lhs, sizeof(d1));
47     memcpy(&d2, rhs, sizeof(d2));
48
49     a = mktime(&d1);
50     b = mktime(&d2);
51
52     if (a < b) {
53         return -1;
54     } else if (a > b) {
55         return 1;
56     }
57
58     return 0;
59 }
60
61 #if 0
62 static void print_tm(struct tm *tm)
63 {
64     printf("%04d-%02d-%02d %02d:%02d:%02d\n",
65            tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
66            tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_gmtoff);
67 }
68 #endif
69
70 static void cmos_get_date_time(struct tm *date)
71 {
72     int base_year = 2000, hour_offset;
73     int sec, min, hour, mday, mon, year;
74     time_t ts;
75     struct tm dummy;
76
77     sec = cmos_read(RTC_SECONDS);
78     min = cmos_read(RTC_MINUTES);
79     hour = cmos_read(RTC_HOURS);
80     mday = cmos_read(RTC_DAY_OF_MONTH);
81     mon = cmos_read(RTC_MONTH);
82     year = cmos_read(RTC_YEAR);
83
84     if ((cmos_read(RTC_REG_B) & REG_B_DM) == 0) {
85         sec = bcd2dec(sec);
86         min = bcd2dec(min);
87         hour = bcd2dec(hour);
88         mday = bcd2dec(mday);
89         mon = bcd2dec(mon);
90         year = bcd2dec(year);
91         hour_offset = 80;
92     } else {
93         hour_offset = 0x80;
94     }
95
96     if ((cmos_read(0x0B) & REG_B_24H) == 0) {
97         if (hour >= hour_offset) {
98             hour -= hour_offset;
99             hour += 12;
100         }
101     }
102
103     ts = time(NULL);
104     localtime_r(&ts, &dummy);
105
106     date->tm_isdst = dummy.tm_isdst;
107     date->tm_sec = sec;
108     date->tm_min = min;
109     date->tm_hour = hour;
110     date->tm_mday = mday;
111     date->tm_mon = mon - 1;
112     date->tm_year = base_year + year - 1900;
113 #ifndef __sun__
114     date->tm_gmtoff = 0;
115 #endif
116
117     ts = mktime(date);
118 }
119
120 static void check_time(int wiggle)
121 {
122     struct tm start, date[4], end;
123     struct tm *datep;
124     time_t ts;
125
126     /*
127      * This check assumes a few things.  First, we cannot guarantee that we get
128      * a consistent reading from the wall clock because we may hit an edge of
129      * the clock while reading.  To work around this, we read four clock readings
130      * such that at least two of them should match.  We need to assume that one
131      * reading is corrupt so we need four readings to ensure that we have at
132      * least two consecutive identical readings
133      *
134      * It's also possible that we'll cross an edge reading the host clock so
135      * simply check to make sure that the clock reading is within the period of
136      * when we expect it to be.
137      */
138
139     ts = time(NULL);
140     gmtime_r(&ts, &start);
141
142     cmos_get_date_time(&date[0]);
143     cmos_get_date_time(&date[1]);
144     cmos_get_date_time(&date[2]);
145     cmos_get_date_time(&date[3]);
146
147     ts = time(NULL);
148     gmtime_r(&ts, &end);
149
150     if (tm_cmp(&date[0], &date[1]) == 0) {
151         datep = &date[0];
152     } else if (tm_cmp(&date[1], &date[2]) == 0) {
153         datep = &date[1];
154     } else if (tm_cmp(&date[2], &date[3]) == 0) {
155         datep = &date[2];
156     } else {
157         g_assert_not_reached();
158     }
159
160     if (!(tm_cmp(&start, datep) <= 0 && tm_cmp(datep, &end) <= 0)) {
161         long t, s;
162
163         start.tm_isdst = datep->tm_isdst;
164
165         t = (long)mktime(datep);
166         s = (long)mktime(&start);
167         if (t < s) {
168             g_test_message("RTC is %ld second(s) behind wall-clock\n", (s - t));
169         } else {
170             g_test_message("RTC is %ld second(s) ahead of wall-clock\n", (t - s));
171         }
172
173         g_assert_cmpint(ABS(t - s), <=, wiggle);
174     }
175 }
176
177 static int wiggle = 2;
178
179 static void set_year_20xx(void)
180 {
181     /* Set BCD mode */
182     cmos_write(RTC_REG_B, REG_B_24H);
183     cmos_write(RTC_REG_A, 0x76);
184     cmos_write(RTC_YEAR, 0x11);
185     cmos_write(RTC_CENTURY, 0x20);
186     cmos_write(RTC_MONTH, 0x02);
187     cmos_write(RTC_DAY_OF_MONTH, 0x02);
188     cmos_write(RTC_HOURS, 0x02);
189     cmos_write(RTC_MINUTES, 0x04);
190     cmos_write(RTC_SECONDS, 0x58);
191     cmos_write(RTC_REG_A, 0x26);
192
193     g_assert_cmpint(cmos_read(RTC_HOURS), ==, 0x02);
194     g_assert_cmpint(cmos_read(RTC_MINUTES), ==, 0x04);
195     g_assert_cmpint(cmos_read(RTC_SECONDS), >=, 0x58);
196     g_assert_cmpint(cmos_read(RTC_DAY_OF_MONTH), ==, 0x02);
197     g_assert_cmpint(cmos_read(RTC_MONTH), ==, 0x02);
198     g_assert_cmpint(cmos_read(RTC_YEAR), ==, 0x11);
199     g_assert_cmpint(cmos_read(RTC_CENTURY), ==, 0x20);
200
201     if (sizeof(time_t) == 4) {
202         return;
203     }
204
205     /* Set a date in 2080 to ensure there is no year-2038 overflow.  */
206     cmos_write(RTC_REG_A, 0x76);
207     cmos_write(RTC_YEAR, 0x80);
208     cmos_write(RTC_REG_A, 0x26);
209
210     g_assert_cmpint(cmos_read(RTC_HOURS), ==, 0x02);
211     g_assert_cmpint(cmos_read(RTC_MINUTES), ==, 0x04);
212     g_assert_cmpint(cmos_read(RTC_SECONDS), >=, 0x58);
213     g_assert_cmpint(cmos_read(RTC_DAY_OF_MONTH), ==, 0x02);
214     g_assert_cmpint(cmos_read(RTC_MONTH), ==, 0x02);
215     g_assert_cmpint(cmos_read(RTC_YEAR), ==, 0x80);
216     g_assert_cmpint(cmos_read(RTC_CENTURY), ==, 0x20);
217
218     cmos_write(RTC_REG_A, 0x76);
219     cmos_write(RTC_YEAR, 0x11);
220     cmos_write(RTC_REG_A, 0x26);
221
222     g_assert_cmpint(cmos_read(RTC_HOURS), ==, 0x02);
223     g_assert_cmpint(cmos_read(RTC_MINUTES), ==, 0x04);
224     g_assert_cmpint(cmos_read(RTC_SECONDS), >=, 0x58);
225     g_assert_cmpint(cmos_read(RTC_DAY_OF_MONTH), ==, 0x02);
226     g_assert_cmpint(cmos_read(RTC_MONTH), ==, 0x02);
227     g_assert_cmpint(cmos_read(RTC_YEAR), ==, 0x11);
228     g_assert_cmpint(cmos_read(RTC_CENTURY), ==, 0x20);
229 }
230
231 static void set_year_1980(void)
232 {
233     /* Set BCD mode */
234     cmos_write(RTC_REG_B, REG_B_24H);
235     cmos_write(RTC_REG_A, 0x76);
236     cmos_write(RTC_YEAR, 0x80);
237     cmos_write(RTC_CENTURY, 0x19);
238     cmos_write(RTC_MONTH, 0x02);
239     cmos_write(RTC_DAY_OF_MONTH, 0x02);
240     cmos_write(RTC_HOURS, 0x02);
241     cmos_write(RTC_MINUTES, 0x04);
242     cmos_write(RTC_SECONDS, 0x58);
243     cmos_write(RTC_REG_A, 0x26);
244
245     g_assert_cmpint(cmos_read(RTC_HOURS), ==, 0x02);
246     g_assert_cmpint(cmos_read(RTC_MINUTES), ==, 0x04);
247     g_assert_cmpint(cmos_read(RTC_SECONDS), >=, 0x58);
248     g_assert_cmpint(cmos_read(RTC_DAY_OF_MONTH), ==, 0x02);
249     g_assert_cmpint(cmos_read(RTC_MONTH), ==, 0x02);
250     g_assert_cmpint(cmos_read(RTC_YEAR), ==, 0x80);
251     g_assert_cmpint(cmos_read(RTC_CENTURY), ==, 0x19);
252 }
253
254 static void bcd_check_time(void)
255 {
256     /* Set BCD mode */
257     cmos_write(RTC_REG_B, REG_B_24H);
258     check_time(wiggle);
259 }
260
261 static void dec_check_time(void)
262 {
263     /* Set DEC mode */
264     cmos_write(RTC_REG_B, REG_B_24H | REG_B_DM);
265     check_time(wiggle);
266 }
267
268 static void alarm_time(void)
269 {
270     struct tm now;
271     time_t ts;
272     int i;
273
274     ts = time(NULL);
275     gmtime_r(&ts, &now);
276
277     /* set DEC mode */
278     cmos_write(RTC_REG_B, REG_B_24H | REG_B_DM);
279
280     g_assert(!get_irq(RTC_ISA_IRQ));
281     cmos_read(RTC_REG_C);
282
283     now.tm_sec = (now.tm_sec + 2) % 60;
284     cmos_write(RTC_SECONDS_ALARM, now.tm_sec);
285     cmos_write(RTC_MINUTES_ALARM, RTC_ALARM_DONT_CARE);
286     cmos_write(RTC_HOURS_ALARM, RTC_ALARM_DONT_CARE);
287     cmos_write(RTC_REG_B, cmos_read(RTC_REG_B) | REG_B_AIE);
288
289     for (i = 0; i < 2 + wiggle; i++) {
290         if (get_irq(RTC_ISA_IRQ)) {
291             break;
292         }
293
294         clock_step(1000000000);
295     }
296
297     g_assert(get_irq(RTC_ISA_IRQ));
298     g_assert((cmos_read(RTC_REG_C) & REG_C_AF) != 0);
299     g_assert(cmos_read(RTC_REG_C) == 0);
300 }
301
302 static void set_time_regs(int h, int m, int s)
303 {
304     cmos_write(RTC_HOURS, h);
305     cmos_write(RTC_MINUTES, m);
306     cmos_write(RTC_SECONDS, s);
307 }
308
309 static void set_time(int mode, int h, int m, int s)
310 {
311     cmos_write(RTC_REG_B, mode);
312     cmos_write(RTC_REG_A, 0x76);
313     set_time_regs(h, m, s);
314     cmos_write(RTC_REG_A, 0x26);
315 }
316
317 static void set_datetime_bcd(int h, int min, int s, int d, int m, int y)
318 {
319     cmos_write(RTC_HOURS, h);
320     cmos_write(RTC_MINUTES, min);
321     cmos_write(RTC_SECONDS, s);
322     cmos_write(RTC_YEAR, y & 0xFF);
323     cmos_write(RTC_CENTURY, y >> 8);
324     cmos_write(RTC_MONTH, m);
325     cmos_write(RTC_DAY_OF_MONTH, d);
326 }
327
328 static void set_datetime_dec(int h, int min, int s, int d, int m, int y)
329 {
330     cmos_write(RTC_HOURS, h);
331     cmos_write(RTC_MINUTES, min);
332     cmos_write(RTC_SECONDS, s);
333     cmos_write(RTC_YEAR, y % 100);
334     cmos_write(RTC_CENTURY, y / 100);
335     cmos_write(RTC_MONTH, m);
336     cmos_write(RTC_DAY_OF_MONTH, d);
337 }
338
339 static void set_datetime(int mode, int h, int min, int s, int d, int m, int y)
340 {
341     cmos_write(RTC_REG_B, mode);
342
343     cmos_write(RTC_REG_A, 0x76);
344     if (mode & REG_B_DM) {
345         set_datetime_dec(h, min, s, d, m, y);
346     } else {
347         set_datetime_bcd(h, min, s, d, m, y);
348     }
349     cmos_write(RTC_REG_A, 0x26);
350 }
351
352 #define assert_time(h, m, s) \
353     do { \
354         g_assert_cmpint(cmos_read(RTC_HOURS), ==, h); \
355         g_assert_cmpint(cmos_read(RTC_MINUTES), ==, m); \
356         g_assert_cmpint(cmos_read(RTC_SECONDS), ==, s); \
357     } while(0)
358
359 #define assert_datetime_bcd(h, min, s, d, m, y) \
360     do { \
361         g_assert_cmpint(cmos_read(RTC_HOURS), ==, h); \
362         g_assert_cmpint(cmos_read(RTC_MINUTES), ==, min); \
363         g_assert_cmpint(cmos_read(RTC_SECONDS), ==, s); \
364         g_assert_cmpint(cmos_read(RTC_DAY_OF_MONTH), ==, d); \
365         g_assert_cmpint(cmos_read(RTC_MONTH), ==, m); \
366         g_assert_cmpint(cmos_read(RTC_YEAR), ==, (y & 0xFF)); \
367         g_assert_cmpint(cmos_read(RTC_CENTURY), ==, (y >> 8)); \
368     } while(0)
369
370 static void basic_12h_bcd(void)
371 {
372     /* set BCD 12 hour mode */
373     set_time(0, 0x81, 0x59, 0x00);
374     clock_step(1000000000LL);
375     assert_time(0x81, 0x59, 0x01);
376     clock_step(59000000000LL);
377     assert_time(0x82, 0x00, 0x00);
378
379     /* test BCD wraparound */
380     set_time(0, 0x09, 0x59, 0x59);
381     clock_step(60000000000LL);
382     assert_time(0x10, 0x00, 0x59);
383
384     /* 12 AM -> 1 AM */
385     set_time(0, 0x12, 0x59, 0x59);
386     clock_step(1000000000LL);
387     assert_time(0x01, 0x00, 0x00);
388
389     /* 12 PM -> 1 PM */
390     set_time(0, 0x92, 0x59, 0x59);
391     clock_step(1000000000LL);
392     assert_time(0x81, 0x00, 0x00);
393
394     /* 11 AM -> 12 PM */
395     set_time(0, 0x11, 0x59, 0x59);
396     clock_step(1000000000LL);
397     assert_time(0x92, 0x00, 0x00);
398     /* TODO: test day wraparound */
399
400     /* 11 PM -> 12 AM */
401     set_time(0, 0x91, 0x59, 0x59);
402     clock_step(1000000000LL);
403     assert_time(0x12, 0x00, 0x00);
404     /* TODO: test day wraparound */
405 }
406
407 static void basic_12h_dec(void)
408 {
409     /* set decimal 12 hour mode */
410     set_time(REG_B_DM, 0x81, 59, 0);
411     clock_step(1000000000LL);
412     assert_time(0x81, 59, 1);
413     clock_step(59000000000LL);
414     assert_time(0x82, 0, 0);
415
416     /* 12 PM -> 1 PM */
417     set_time(REG_B_DM, 0x8c, 59, 59);
418     clock_step(1000000000LL);
419     assert_time(0x81, 0, 0);
420
421     /* 12 AM -> 1 AM */
422     set_time(REG_B_DM, 0x0c, 59, 59);
423     clock_step(1000000000LL);
424     assert_time(0x01, 0, 0);
425
426     /* 11 AM -> 12 PM */
427     set_time(REG_B_DM, 0x0b, 59, 59);
428     clock_step(1000000000LL);
429     assert_time(0x8c, 0, 0);
430
431     /* 11 PM -> 12 AM */
432     set_time(REG_B_DM, 0x8b, 59, 59);
433     clock_step(1000000000LL);
434     assert_time(0x0c, 0, 0);
435     /* TODO: test day wraparound */
436 }
437
438 static void basic_24h_bcd(void)
439 {
440     /* set BCD 24 hour mode */
441     set_time(REG_B_24H, 0x09, 0x59, 0x00);
442     clock_step(1000000000LL);
443     assert_time(0x09, 0x59, 0x01);
444     clock_step(59000000000LL);
445     assert_time(0x10, 0x00, 0x00);
446
447     /* test BCD wraparound */
448     set_time(REG_B_24H, 0x09, 0x59, 0x00);
449     clock_step(60000000000LL);
450     assert_time(0x10, 0x00, 0x00);
451
452     /* TODO: test day wraparound */
453     set_time(REG_B_24H, 0x23, 0x59, 0x00);
454     clock_step(60000000000LL);
455     assert_time(0x00, 0x00, 0x00);
456 }
457
458 static void basic_24h_dec(void)
459 {
460     /* set decimal 24 hour mode */
461     set_time(REG_B_24H | REG_B_DM, 9, 59, 0);
462     clock_step(1000000000LL);
463     assert_time(9, 59, 1);
464     clock_step(59000000000LL);
465     assert_time(10, 0, 0);
466
467     /* test BCD wraparound */
468     set_time(REG_B_24H | REG_B_DM, 9, 59, 0);
469     clock_step(60000000000LL);
470     assert_time(10, 0, 0);
471
472     /* TODO: test day wraparound */
473     set_time(REG_B_24H | REG_B_DM, 23, 59, 0);
474     clock_step(60000000000LL);
475     assert_time(0, 0, 0);
476 }
477
478 static void am_pm_alarm(void)
479 {
480     cmos_write(RTC_MINUTES_ALARM, 0xC0);
481     cmos_write(RTC_SECONDS_ALARM, 0xC0);
482
483     /* set BCD 12 hour mode */
484     cmos_write(RTC_REG_B, 0);
485
486     /* Set time and alarm hour.  */
487     cmos_write(RTC_REG_A, 0x76);
488     cmos_write(RTC_HOURS_ALARM, 0x82);
489     cmos_write(RTC_HOURS, 0x81);
490     cmos_write(RTC_MINUTES, 0x59);
491     cmos_write(RTC_SECONDS, 0x00);
492     cmos_read(RTC_REG_C);
493     cmos_write(RTC_REG_A, 0x26);
494
495     /* Check that alarm triggers when AM/PM is set.  */
496     clock_step(60000000000LL);
497     g_assert(cmos_read(RTC_HOURS) == 0x82);
498     g_assert((cmos_read(RTC_REG_C) & REG_C_AF) != 0);
499
500     /*
501      * Each of the following two tests takes over 60 seconds due to the time
502      * needed to report the PIT interrupts.  Unfortunately, our PIT device
503      * model keeps counting even when GATE=0, so we cannot simply disable
504      * it in main().
505      */
506     if (g_test_quick()) {
507         return;
508     }
509
510     /* set DEC 12 hour mode */
511     cmos_write(RTC_REG_B, REG_B_DM);
512
513     /* Set time and alarm hour.  */
514     cmos_write(RTC_REG_A, 0x76);
515     cmos_write(RTC_HOURS_ALARM, 0x82);
516     cmos_write(RTC_HOURS, 3);
517     cmos_write(RTC_MINUTES, 0);
518     cmos_write(RTC_SECONDS, 0);
519     cmos_read(RTC_REG_C);
520     cmos_write(RTC_REG_A, 0x26);
521
522     /* Check that alarm triggers.  */
523     clock_step(3600 * 11 * 1000000000LL);
524     g_assert(cmos_read(RTC_HOURS) == 0x82);
525     g_assert((cmos_read(RTC_REG_C) & REG_C_AF) != 0);
526
527     /* Same as above, with inverted HOURS and HOURS_ALARM.  */
528     cmos_write(RTC_REG_A, 0x76);
529     cmos_write(RTC_HOURS_ALARM, 2);
530     cmos_write(RTC_HOURS, 3);
531     cmos_write(RTC_MINUTES, 0);
532     cmos_write(RTC_SECONDS, 0);
533     cmos_read(RTC_REG_C);
534     cmos_write(RTC_REG_A, 0x26);
535
536     /* Check that alarm does not trigger if hours differ only by AM/PM.  */
537     clock_step(3600 * 11 * 1000000000LL);
538     g_assert(cmos_read(RTC_HOURS) == 0x82);
539     g_assert((cmos_read(RTC_REG_C) & REG_C_AF) == 0);
540 }
541
542 /* success if no crash or abort */
543 static void fuzz_registers(void)
544 {
545     unsigned int i;
546
547     for (i = 0; i < 1000; i++) {
548         uint8_t reg, val;
549
550         reg = (uint8_t)g_test_rand_int_range(0, 16);
551         val = (uint8_t)g_test_rand_int_range(0, 256);
552
553         cmos_write(reg, val);
554         cmos_read(reg);
555     }
556 }
557
558 static void register_b_set_flag(void)
559 {
560     if (cmos_read(RTC_REG_A) & REG_A_UIP) {
561         clock_step(UIP_HOLD_LENGTH + NANOSECONDS_PER_SECOND / 5);
562     }
563     g_assert_cmpint(cmos_read(RTC_REG_A) & REG_A_UIP, ==, 0);
564
565     /* Enable binary-coded decimal (BCD) mode and SET flag in Register B*/
566     cmos_write(RTC_REG_B, REG_B_24H | REG_B_SET);
567
568     set_datetime_bcd(0x02, 0x04, 0x58, 0x02, 0x02, 0x2011);
569
570     assert_datetime_bcd(0x02, 0x04, 0x58, 0x02, 0x02, 0x2011);
571
572     /* Since SET flag is still enabled, time does not advance. */
573     clock_step(1000000000LL);
574     assert_datetime_bcd(0x02, 0x04, 0x58, 0x02, 0x02, 0x2011);
575
576     /* Disable SET flag in Register B */
577     cmos_write(RTC_REG_B, cmos_read(RTC_REG_B) & ~REG_B_SET);
578
579     assert_datetime_bcd(0x02, 0x04, 0x58, 0x02, 0x02, 0x2011);
580
581     /* Since SET flag is disabled, the clock now advances.  */
582     clock_step(1000000000LL);
583     assert_datetime_bcd(0x02, 0x04, 0x59, 0x02, 0x02, 0x2011);
584 }
585
586 static void divider_reset(void)
587 {
588     /* Enable binary-coded decimal (BCD) mode in Register B*/
589     cmos_write(RTC_REG_B, REG_B_24H);
590
591     /* Enter divider reset */
592     cmos_write(RTC_REG_A, 0x76);
593     set_datetime_bcd(0x02, 0x04, 0x58, 0x02, 0x02, 0x2011);
594
595     assert_datetime_bcd(0x02, 0x04, 0x58, 0x02, 0x02, 0x2011);
596
597     /* Since divider reset flag is still enabled, these are equality checks. */
598     clock_step(1000000000LL);
599     assert_datetime_bcd(0x02, 0x04, 0x58, 0x02, 0x02, 0x2011);
600
601     /* The first update ends 500 ms after divider reset */
602     cmos_write(RTC_REG_A, 0x26);
603     clock_step(500000000LL - UIP_HOLD_LENGTH - 1);
604     g_assert_cmpint(cmos_read(RTC_REG_A) & REG_A_UIP, ==, 0);
605     assert_datetime_bcd(0x02, 0x04, 0x58, 0x02, 0x02, 0x2011);
606
607     clock_step(1);
608     g_assert_cmpint(cmos_read(RTC_REG_A) & REG_A_UIP, !=, 0);
609     clock_step(UIP_HOLD_LENGTH);
610     g_assert_cmpint(cmos_read(RTC_REG_A) & REG_A_UIP, ==, 0);
611
612     assert_datetime_bcd(0x02, 0x04, 0x59, 0x02, 0x02, 0x2011);
613 }
614
615 static void uip_stuck(void)
616 {
617     set_datetime(REG_B_24H, 0x02, 0x04, 0x58, 0x02, 0x02, 0x2011);
618
619     /* The first update ends 500 ms after divider reset */
620     (void)cmos_read(RTC_REG_C);
621     clock_step(500000000LL);
622     g_assert_cmpint(cmos_read(RTC_REG_A) & REG_A_UIP, ==, 0);
623     assert_datetime_bcd(0x02, 0x04, 0x59, 0x02, 0x02, 0x2011);
624
625     /* UF is now set.  */
626     cmos_write(RTC_HOURS_ALARM, 0x02);
627     cmos_write(RTC_MINUTES_ALARM, 0xC0);
628     cmos_write(RTC_SECONDS_ALARM, 0xC0);
629
630     /* Because the alarm will fire soon, reading register A will latch UIP.  */
631     clock_step(1000000000LL - UIP_HOLD_LENGTH / 2);
632     g_assert_cmpint(cmos_read(RTC_REG_A) & REG_A_UIP, !=, 0);
633
634     /* Move the alarm far away.  This must not cause UIP to remain stuck!  */
635     cmos_write(RTC_HOURS_ALARM, 0x03);
636     clock_step(UIP_HOLD_LENGTH);
637     g_assert_cmpint(cmos_read(RTC_REG_A) & REG_A_UIP, ==, 0);
638 }
639
640 #define RTC_PERIOD_CODE1    13   /* 8 Hz */
641 #define RTC_PERIOD_CODE2    15   /* 2 Hz */
642
643 #define RTC_PERIOD_TEST_NR  50
644
645 static uint64_t wait_periodic_interrupt(uint64_t real_time)
646 {
647     while (!get_irq(RTC_ISA_IRQ)) {
648         real_time = clock_step_next();
649     }
650
651     g_assert((cmos_read(RTC_REG_C) & REG_C_PF) != 0);
652     return real_time;
653 }
654
655 static void periodic_timer(void)
656 {
657     int i;
658     uint64_t period_clocks, period_time, start_time, real_time;
659
660     /* disable all interrupts. */
661     cmos_write(RTC_REG_B, cmos_read(RTC_REG_B) &
662                                    ~(REG_B_PIE | REG_B_AIE | REG_B_UIE));
663     cmos_write(RTC_REG_A, RTC_PERIOD_CODE1);
664     /* enable periodic interrupt after properly configure the period. */
665     cmos_write(RTC_REG_B, cmos_read(RTC_REG_B) | REG_B_PIE);
666
667     start_time = real_time = clock_step_next();
668
669     for (i = 0; i < RTC_PERIOD_TEST_NR; i++) {
670         cmos_write(RTC_REG_A, RTC_PERIOD_CODE1);
671         real_time = wait_periodic_interrupt(real_time);
672         cmos_write(RTC_REG_A, RTC_PERIOD_CODE2);
673         real_time = wait_periodic_interrupt(real_time);
674     }
675
676     period_clocks = periodic_period_to_clock(RTC_PERIOD_CODE1) +
677                        periodic_period_to_clock(RTC_PERIOD_CODE2);
678     period_clocks *= RTC_PERIOD_TEST_NR;
679     period_time = periodic_clock_to_ns(period_clocks);
680
681     real_time -= start_time;
682     g_assert_cmpint(ABS((int64_t)(real_time - period_time)), <=,
683                     NANOSECONDS_PER_SECOND * 0.5);
684 }
685
686 int main(int argc, char **argv)
687 {
688     QTestState *s = NULL;
689     int ret;
690
691     g_test_init(&argc, &argv, NULL);
692
693     s = qtest_start("-rtc clock=vm");
694     qtest_irq_intercept_in(s, "ioapic");
695
696     qtest_add_func("/rtc/check-time/bcd", bcd_check_time);
697     qtest_add_func("/rtc/check-time/dec", dec_check_time);
698     qtest_add_func("/rtc/alarm/interrupt", alarm_time);
699     qtest_add_func("/rtc/alarm/am-pm", am_pm_alarm);
700     qtest_add_func("/rtc/basic/dec-24h", basic_24h_dec);
701     qtest_add_func("/rtc/basic/bcd-24h", basic_24h_bcd);
702     qtest_add_func("/rtc/basic/dec-12h", basic_12h_dec);
703     qtest_add_func("/rtc/basic/bcd-12h", basic_12h_bcd);
704     qtest_add_func("/rtc/set-year/20xx", set_year_20xx);
705     qtest_add_func("/rtc/set-year/1980", set_year_1980);
706     qtest_add_func("/rtc/update/register_b_set_flag", register_b_set_flag);
707     qtest_add_func("/rtc/update/divider-reset", divider_reset);
708     qtest_add_func("/rtc/update/uip-stuck", uip_stuck);
709     qtest_add_func("/rtc/misc/fuzz-registers", fuzz_registers);
710     qtest_add_func("/rtc/periodic/interrupt", periodic_timer);
711
712     ret = g_test_run();
713
714     if (s) {
715         qtest_quit(s);
716     }
717
718     return ret;
719 }
This page took 0.061337 seconds and 4 git commands to generate.