Annotation of qemu/tests/m48t59-test.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * QTest testcase for the M48T59 and M48T08 real-time clocks
                      3:  *
                      4:  * Based on MC146818 RTC test:
                      5:  * Copyright IBM, Corp. 2012
                      6:  *
                      7:  * Authors:
                      8:  *  Anthony Liguori   <[email protected]>
                      9:  *
                     10:  * This work is licensed under the terms of the GNU GPL, version 2 or later.
                     11:  * See the COPYING file in the top-level directory.
                     12:  *
                     13:  */
                     14: #include "libqtest.h"
                     15: 
                     16: #include <glib.h>
                     17: #include <stdio.h>
                     18: #include <string.h>
                     19: #include <stdlib.h>
                     20: #include <unistd.h>
                     21: 
                     22: #define RTC_SECONDS             0x9
                     23: #define RTC_MINUTES             0xa
                     24: #define RTC_HOURS               0xb
                     25: 
                     26: #define RTC_DAY_OF_WEEK         0xc
                     27: #define RTC_DAY_OF_MONTH        0xd
                     28: #define RTC_MONTH               0xe
                     29: #define RTC_YEAR                0xf
                     30: 
                     31: static uint32_t base;
                     32: static uint16_t reg_base = 0x1ff0; /* 0x7f0 for m48t02 */
                     33: static int base_year;
                     34: static bool use_mmio;
                     35: 
                     36: static uint8_t cmos_read_mmio(uint8_t reg)
                     37: {
                     38:     uint8_t data;
                     39: 
                     40:     memread(base + (uint32_t)reg_base + (uint32_t)reg, &data, 1);
                     41:     return data;
                     42: }
                     43: 
                     44: static void cmos_write_mmio(uint8_t reg, uint8_t val)
                     45: {
                     46:     uint8_t data = val;
                     47: 
                     48:     memwrite(base + (uint32_t)reg_base + (uint32_t)reg, &data, 1);
                     49: }
                     50: 
                     51: static uint8_t cmos_read_ioio(uint8_t reg)
                     52: {
                     53:     outw(base + 0, reg_base + (uint16_t)reg);
                     54:     return inb(base + 3);
                     55: }
                     56: 
                     57: static void cmos_write_ioio(uint8_t reg, uint8_t val)
                     58: {
                     59:     outw(base + 0, reg_base + (uint16_t)reg);
                     60:     outb(base + 3, val);
                     61: }
                     62: 
                     63: static uint8_t cmos_read(uint8_t reg)
                     64: {
                     65:     if (use_mmio) {
                     66:         return cmos_read_mmio(reg);
                     67:     } else {
                     68:         return cmos_read_ioio(reg);
                     69:     }
                     70: }
                     71: 
                     72: static void cmos_write(uint8_t reg, uint8_t val)
                     73: {
                     74:     if (use_mmio) {
                     75:         cmos_write_mmio(reg, val);
                     76:     } else {
                     77:         cmos_write_ioio(reg, val);
                     78:     }
                     79: }
                     80: 
                     81: static int bcd2dec(int value)
                     82: {
                     83:     return (((value >> 4) & 0x0F) * 10) + (value & 0x0F);
                     84: }
                     85: 
                     86: static int tm_cmp(struct tm *lhs, struct tm *rhs)
                     87: {
                     88:     time_t a, b;
                     89:     struct tm d1, d2;
                     90: 
                     91:     memcpy(&d1, lhs, sizeof(d1));
                     92:     memcpy(&d2, rhs, sizeof(d2));
                     93: 
                     94:     a = mktime(&d1);
                     95:     b = mktime(&d2);
                     96: 
                     97:     if (a < b) {
                     98:         return -1;
                     99:     } else if (a > b) {
                    100:         return 1;
                    101:     }
                    102: 
                    103:     return 0;
                    104: }
                    105: 
                    106: #if 0
                    107: static void print_tm(struct tm *tm)
                    108: {
                    109:     printf("%04d-%02d-%02d %02d:%02d:%02d %+02ld\n",
                    110:            tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
                    111:            tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_gmtoff);
                    112: }
                    113: #endif
                    114: 
                    115: static void cmos_get_date_time(struct tm *date)
                    116: {
                    117:     int sec, min, hour, mday, mon, year;
                    118:     time_t ts;
                    119:     struct tm dummy;
                    120: 
                    121:     sec = cmos_read(RTC_SECONDS);
                    122:     min = cmos_read(RTC_MINUTES);
                    123:     hour = cmos_read(RTC_HOURS);
                    124:     mday = cmos_read(RTC_DAY_OF_MONTH);
                    125:     mon = cmos_read(RTC_MONTH);
                    126:     year = cmos_read(RTC_YEAR);
                    127: 
                    128:     sec = bcd2dec(sec);
                    129:     min = bcd2dec(min);
                    130:     hour = bcd2dec(hour);
                    131:     mday = bcd2dec(mday);
                    132:     mon = bcd2dec(mon);
                    133:     year = bcd2dec(year);
                    134: 
                    135:     ts = time(NULL);
                    136:     localtime_r(&ts, &dummy);
                    137: 
                    138:     date->tm_isdst = dummy.tm_isdst;
                    139:     date->tm_sec = sec;
                    140:     date->tm_min = min;
                    141:     date->tm_hour = hour;
                    142:     date->tm_mday = mday;
                    143:     date->tm_mon = mon - 1;
                    144:     date->tm_year = base_year + year - 1900;
                    145:     date->tm_gmtoff = 0;
                    146: 
                    147:     ts = mktime(date);
                    148: }
                    149: 
                    150: static void check_time(int wiggle)
                    151: {
                    152:     struct tm start, date[4], end;
                    153:     struct tm *datep;
                    154:     time_t ts;
                    155: 
                    156:     /*
                    157:      * This check assumes a few things.  First, we cannot guarantee that we get
                    158:      * a consistent reading from the wall clock because we may hit an edge of
                    159:      * the clock while reading.  To work around this, we read four clock readings
                    160:      * such that at least two of them should match.  We need to assume that one
                    161:      * reading is corrupt so we need four readings to ensure that we have at
                    162:      * least two consecutive identical readings
                    163:      *
                    164:      * It's also possible that we'll cross an edge reading the host clock so
                    165:      * simply check to make sure that the clock reading is within the period of
                    166:      * when we expect it to be.
                    167:      */
                    168: 
                    169:     ts = time(NULL);
                    170:     gmtime_r(&ts, &start);
                    171: 
                    172:     cmos_get_date_time(&date[0]);
                    173:     cmos_get_date_time(&date[1]);
                    174:     cmos_get_date_time(&date[2]);
                    175:     cmos_get_date_time(&date[3]);
                    176: 
                    177:     ts = time(NULL);
                    178:     gmtime_r(&ts, &end);
                    179: 
                    180:     if (tm_cmp(&date[0], &date[1]) == 0) {
                    181:         datep = &date[0];
                    182:     } else if (tm_cmp(&date[1], &date[2]) == 0) {
                    183:         datep = &date[1];
                    184:     } else if (tm_cmp(&date[2], &date[3]) == 0) {
                    185:         datep = &date[2];
                    186:     } else {
                    187:         g_assert_not_reached();
                    188:     }
                    189: 
                    190:     if (!(tm_cmp(&start, datep) <= 0 && tm_cmp(datep, &end) <= 0)) {
                    191:         long t, s;
                    192: 
                    193:         start.tm_isdst = datep->tm_isdst;
                    194: 
                    195:         t = (long)mktime(datep);
                    196:         s = (long)mktime(&start);
                    197:         if (t < s) {
                    198:             g_test_message("RTC is %ld second(s) behind wall-clock\n", (s - t));
                    199:         } else {
                    200:             g_test_message("RTC is %ld second(s) ahead of wall-clock\n", (t - s));
                    201:         }
                    202: 
                    203:         g_assert_cmpint(ABS(t - s), <=, wiggle);
                    204:     }
                    205: }
                    206: 
                    207: static int wiggle = 2;
                    208: 
                    209: static void bcd_check_time(void)
                    210: {
                    211:     if (strcmp(qtest_get_arch(), "sparc64") == 0) {
                    212:         base = 0x74;
                    213:         base_year = 1900;
                    214:         use_mmio = false;
                    215:     } else if (strcmp(qtest_get_arch(), "sparc") == 0) {
                    216:         base = 0x71200000;
                    217:         base_year = 1968;
                    218:         use_mmio = true;
                    219:     } else { /* PPC: need to map macio in PCI */
                    220:         g_assert_not_reached();
                    221:     }
                    222:     check_time(wiggle);
                    223: }
                    224: 
                    225: /* success if no crash or abort */
                    226: static void fuzz_registers(void)
                    227: {
                    228:     unsigned int i;
                    229: 
                    230:     for (i = 0; i < 1000; i++) {
                    231:         uint8_t reg, val;
                    232: 
                    233:         reg = (uint8_t)g_test_rand_int_range(0, 16);
                    234:         val = (uint8_t)g_test_rand_int_range(0, 256);
                    235: 
                    236:         cmos_write(reg, val);
                    237:         cmos_read(reg);
                    238:     }
                    239: }
                    240: 
                    241: int main(int argc, char **argv)
                    242: {
                    243:     QTestState *s = NULL;
                    244:     int ret;
                    245: 
                    246:     g_test_init(&argc, &argv, NULL);
                    247: 
                    248:     s = qtest_start("-display none -rtc clock=vm");
                    249: 
                    250:     qtest_add_func("/rtc/bcd/check-time", bcd_check_time);
                    251:     qtest_add_func("/rtc/fuzz-registers", fuzz_registers);
                    252:     ret = g_test_run();
                    253: 
                    254:     if (s) {
                    255:         qtest_quit(s);
                    256:     }
                    257: 
                    258:     return ret;
                    259: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.