xref: /kvm-unit-tests/powerpc/rtas.c (revision a9abb1b82d6d6bd0821a7234433b4de975e2245f)
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 
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 
40e3892e10SLaurent Vivier static void check_get_time_of_day(unsigned long start)
41e3892e10SLaurent Vivier {
42e3892e10SLaurent Vivier 	int token;
43e3892e10SLaurent Vivier 	int ret;
44e3892e10SLaurent Vivier 	int now[8];
45e3892e10SLaurent Vivier 	unsigned long t1, t2, count;
46e3892e10SLaurent Vivier 
47e3892e10SLaurent Vivier 	token = rtas_token("get-time-of-day");
48e3892e10SLaurent Vivier 	report("token available", token != RTAS_UNKNOWN_SERVICE);
49e3892e10SLaurent Vivier 	if (token == RTAS_UNKNOWN_SERVICE)
50e3892e10SLaurent Vivier 		return;
51e3892e10SLaurent Vivier 
52e3892e10SLaurent Vivier 	ret = rtas_call(token, 0, 8, now);
53e3892e10SLaurent Vivier 	report("execution", ret == 0);
54e3892e10SLaurent Vivier 
55e3892e10SLaurent Vivier 	report("second",  now[5] >= 0 && now[5] <= 59);
56e3892e10SLaurent Vivier 	report("minute", now[4] >= 0 && now[4] <= 59);
57e3892e10SLaurent Vivier 	report("hour", now[3] >= 0 && now[3] <= 23);
58e3892e10SLaurent Vivier 	report("day", now[2] >= 1 && now[2] <= 31);
59e3892e10SLaurent Vivier 	report("month", now[1] >= 1 && now[1] <= 12);
60e3892e10SLaurent Vivier 	report("year", now[0] >= 1970);
61e3892e10SLaurent Vivier 	report("accuracy (< 3s)", mktime(now[0], now[1], now[2],
62e3892e10SLaurent Vivier 					 now[3], now[4], now[5]) - start < 3);
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);
72e3892e10SLaurent Vivier 	report("running", t1 + DELAY <= t2);
73e3892e10SLaurent Vivier }
74e3892e10SLaurent Vivier 
75e3892e10SLaurent Vivier static void check_set_time_of_day(void)
76e3892e10SLaurent Vivier {
77e3892e10SLaurent Vivier 	int token;
78e3892e10SLaurent Vivier 	int ret;
79e3892e10SLaurent Vivier 	int date[8];
80e3892e10SLaurent Vivier 	unsigned long t1, t2, count;
81e3892e10SLaurent Vivier 
82e3892e10SLaurent Vivier 	token = rtas_token("set-time-of-day");
83e3892e10SLaurent Vivier 	report("token available", token != RTAS_UNKNOWN_SERVICE);
84e3892e10SLaurent Vivier 	if (token == RTAS_UNKNOWN_SERVICE)
85e3892e10SLaurent Vivier 		return;
86e3892e10SLaurent Vivier 
87e3892e10SLaurent Vivier 	/* 23:59:59 28/2/2000 */
88e3892e10SLaurent Vivier 
89e3892e10SLaurent Vivier 	ret = rtas_call(token, 7, 1, NULL, 2000, 2, 28, 23, 59, 59);
90e3892e10SLaurent Vivier 	report("execution", ret == 0);
91e3892e10SLaurent Vivier 
92e3892e10SLaurent Vivier 	/* check it has worked */
93e3892e10SLaurent Vivier 	ret = rtas_call(rtas_token("get-time-of-day"), 0, 8, date);
94e3892e10SLaurent Vivier 	report("re-read", ret == 0);
95e3892e10SLaurent Vivier 	t1 = mktime(2000, 2, 28, 23, 59, 59);
96e3892e10SLaurent Vivier 	t2 = mktime(date[0], date[1], date[2],
97e3892e10SLaurent Vivier 		    date[3], date[4], date[5]);
98e3892e10SLaurent Vivier 	report("result", t2 - t1 < 2);
99e3892e10SLaurent Vivier 
100e3892e10SLaurent Vivier 	/* check it is running */
101e3892e10SLaurent Vivier 	count = 0;
102e3892e10SLaurent Vivier 	do {
103e3892e10SLaurent Vivier 		ret = rtas_call(rtas_token("get-time-of-day"), 0, 8, date);
104e3892e10SLaurent Vivier 		t2 = mktime(date[0], date[1], date[2],
105e3892e10SLaurent Vivier 			    date[3], date[4], date[5]);
106e3892e10SLaurent Vivier 		count++;
107e3892e10SLaurent Vivier 	} while (t1 + DELAY > t2 && count < MAX_LOOP);
108e3892e10SLaurent Vivier 	report("running", t1 + DELAY <= t2);
109e3892e10SLaurent Vivier }
110e3892e10SLaurent Vivier 
111e3892e10SLaurent Vivier int main(int argc, char **argv)
112e3892e10SLaurent Vivier {
113e3892e10SLaurent Vivier 	int len;
114e3892e10SLaurent Vivier 	long val;
115e3892e10SLaurent Vivier 
116e3892e10SLaurent Vivier 	report_prefix_push("rtas");
117e3892e10SLaurent Vivier 
118*a9abb1b8SAndrew Jones 	if (argc < 2)
119e3892e10SLaurent Vivier 		report_abort("no test specified");
120e3892e10SLaurent Vivier 
121*a9abb1b8SAndrew Jones 	report_prefix_push(argv[1]);
122e3892e10SLaurent Vivier 
123*a9abb1b8SAndrew Jones 	if (strcmp(argv[1], "get-time-of-day") == 0) {
124e3892e10SLaurent Vivier 
125*a9abb1b8SAndrew Jones 		len = parse_keyval(argv[2], &val);
126e3892e10SLaurent Vivier 		if (len == -1) {
127e3892e10SLaurent Vivier 			printf("Missing parameter \"date\"\n");
128e3892e10SLaurent Vivier 			abort();
129e3892e10SLaurent Vivier 		}
130*a9abb1b8SAndrew Jones 		argv[2][len] = '\0';
131e3892e10SLaurent Vivier 
132e3892e10SLaurent Vivier 		check_get_time_of_day(val);
133e3892e10SLaurent Vivier 
134*a9abb1b8SAndrew Jones 	} else if (strcmp(argv[1], "set-time-of-day") == 0) {
135e3892e10SLaurent Vivier 
136e3892e10SLaurent Vivier 		check_set_time_of_day();
137e3892e10SLaurent Vivier 
138e3892e10SLaurent Vivier 	} else {
139e3892e10SLaurent Vivier 		printf("Unknown subtest\n");
140e3892e10SLaurent Vivier 		abort();
141e3892e10SLaurent Vivier 	}
142e3892e10SLaurent Vivier 
143e3892e10SLaurent Vivier 	report_prefix_pop();
144e3892e10SLaurent Vivier 
145e3892e10SLaurent Vivier 	report_prefix_pop();
146e3892e10SLaurent Vivier 
147e3892e10SLaurent Vivier 	return report_summary();
148e3892e10SLaurent Vivier }
149