qemu/tests/qtest/rtc-test.c
<<
>>
Prefs
   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
  23static uint8_t base = 0x70;
  24
  25static int bcd2dec(int value)
  26{
  27    return (((value >> 4) & 0x0F) * 10) + (value & 0x0F);
  28}
  29
  30static uint8_t cmos_read(uint8_t reg)
  31{
  32    outb(base + 0, reg);
  33    return inb(base + 1);
  34}
  35
  36static void cmos_write(uint8_t reg, uint8_t val)
  37{
  38    outb(base + 0, reg);
  39    outb(base + 1, val);
  40}
  41
  42static 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
  63static 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
  71static 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#ifndef __sun__
 115    date->tm_gmtoff = 0;
 116#endif
 117
 118    ts = mktime(date);
 119}
 120
 121static 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
 178static int wiggle = 2;
 179
 180static 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
 232static 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
 255static 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
 262static 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
 269static 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
 303static 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
 310static 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
 318static 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
 329static 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
 340static 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
 371static 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
 408static 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
 439static 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
 459static 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
 479static 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 */
 544static 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
 559static 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
 587static 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
 616static 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
 646static 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
 656static 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
 687int 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}
 719