Annotation of qemu/tests/m48t59-test.c, revision 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.