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