xref: /kvm-unit-tests/powerpc/rtas.c (revision a9abb1b82d6d6bd0821a7234433b4de975e2245f)
1 /*
2  * Test the RTAS interface
3  */
4 
5 #include <libcflat.h>
6 #include <util.h>
7 #include <asm/rtas.h>
8 
9 #define DAYS(y,m,d) (365UL * (y) + ((y) / 4) - ((y) / 100) + ((y) / 400) + \
10 		     367UL * (m) / 12  + \
11 		     (d))
12 
13 static unsigned long mktime(int year, int month, int day,
14 			    int hour, int minute, int second)
15 {
16 	unsigned long epoch;
17 
18 	/* Put February at end of the year to avoid leap day this year */
19 
20 	month -= 2;
21 	if (month <= 0) {
22 		month += 12;
23 		year -= 1;
24 	}
25 
26 	/* compute epoch: substract DAYS(since_March(1-1-1970)) */
27 
28 	epoch = DAYS(year, month, day) - DAYS(1969, 11, 1);
29 
30 	epoch = epoch * 24 + hour;
31 	epoch = epoch * 60 + minute;
32 	epoch = epoch * 60 + second;
33 
34 	return epoch;
35 }
36 
37 #define DELAY 1
38 #define MAX_LOOP 10000000
39 
40 static void check_get_time_of_day(unsigned long start)
41 {
42 	int token;
43 	int ret;
44 	int now[8];
45 	unsigned long t1, t2, count;
46 
47 	token = rtas_token("get-time-of-day");
48 	report("token available", token != RTAS_UNKNOWN_SERVICE);
49 	if (token == RTAS_UNKNOWN_SERVICE)
50 		return;
51 
52 	ret = rtas_call(token, 0, 8, now);
53 	report("execution", ret == 0);
54 
55 	report("second",  now[5] >= 0 && now[5] <= 59);
56 	report("minute", now[4] >= 0 && now[4] <= 59);
57 	report("hour", now[3] >= 0 && now[3] <= 23);
58 	report("day", now[2] >= 1 && now[2] <= 31);
59 	report("month", now[1] >= 1 && now[1] <= 12);
60 	report("year", now[0] >= 1970);
61 	report("accuracy (< 3s)", mktime(now[0], now[1], now[2],
62 					 now[3], now[4], now[5]) - start < 3);
63 
64 	ret = rtas_call(token, 0, 8, now);
65 	t1 = mktime(now[0], now[1], now[2], now[3], now[4], now[5]);
66 	count = 0;
67 	do {
68 		ret = rtas_call(token, 0, 8, now);
69 		t2 = mktime(now[0], now[1], now[2], now[3], now[4], now[5]);
70 		count++;
71 	} while (t1 + DELAY > t2 && count < MAX_LOOP);
72 	report("running", t1 + DELAY <= t2);
73 }
74 
75 static void check_set_time_of_day(void)
76 {
77 	int token;
78 	int ret;
79 	int date[8];
80 	unsigned long t1, t2, count;
81 
82 	token = rtas_token("set-time-of-day");
83 	report("token available", token != RTAS_UNKNOWN_SERVICE);
84 	if (token == RTAS_UNKNOWN_SERVICE)
85 		return;
86 
87 	/* 23:59:59 28/2/2000 */
88 
89 	ret = rtas_call(token, 7, 1, NULL, 2000, 2, 28, 23, 59, 59);
90 	report("execution", ret == 0);
91 
92 	/* check it has worked */
93 	ret = rtas_call(rtas_token("get-time-of-day"), 0, 8, date);
94 	report("re-read", ret == 0);
95 	t1 = mktime(2000, 2, 28, 23, 59, 59);
96 	t2 = mktime(date[0], date[1], date[2],
97 		    date[3], date[4], date[5]);
98 	report("result", t2 - t1 < 2);
99 
100 	/* check it is running */
101 	count = 0;
102 	do {
103 		ret = rtas_call(rtas_token("get-time-of-day"), 0, 8, date);
104 		t2 = mktime(date[0], date[1], date[2],
105 			    date[3], date[4], date[5]);
106 		count++;
107 	} while (t1 + DELAY > t2 && count < MAX_LOOP);
108 	report("running", t1 + DELAY <= t2);
109 }
110 
111 int main(int argc, char **argv)
112 {
113 	int len;
114 	long val;
115 
116 	report_prefix_push("rtas");
117 
118 	if (argc < 2)
119 		report_abort("no test specified");
120 
121 	report_prefix_push(argv[1]);
122 
123 	if (strcmp(argv[1], "get-time-of-day") == 0) {
124 
125 		len = parse_keyval(argv[2], &val);
126 		if (len == -1) {
127 			printf("Missing parameter \"date\"\n");
128 			abort();
129 		}
130 		argv[2][len] = '\0';
131 
132 		check_get_time_of_day(val);
133 
134 	} else if (strcmp(argv[1], "set-time-of-day") == 0) {
135 
136 		check_set_time_of_day();
137 
138 	} else {
139 		printf("Unknown subtest\n");
140 		abort();
141 	}
142 
143 	report_prefix_pop();
144 
145 	report_prefix_pop();
146 
147 	return report_summary();
148 }
149