qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

rtc-test.c (20562B)


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